JVMTI OOM handling when arrays / objects are too large

Jeremy Manson jeremymanson at google.com
Fri Jun 5 14:25:39 PDT 2009


Hi folks,

I was talking to some of the HS team at JavaOne, and they encouraged
me to send some of the patches that we are working on at Google back
to Sun.  (Everyone at Google is covered under a blanket SCA, so we can
contribute back anything done by any Googler).

To get started and test the waters, and because I have never tried to
contribute to OpenJDK before, I thought I would send on a
nearly-trivial fix that I made last year in response to a user
complaint.  The issue was that when the user specifies
-XX:OnOutOfMemoryError, and the OOM is thrown because a single memory
allocation was too close to Integer.MAX_VALUE, the OnOutOfMemoryError
command would not be executed.  I've attached the patch.  Let me know
what I should do to proceed.

Thanks!

Jeremy
-------------- next part --------------
# HG changeset patch
# User jeremymanson at iago.mtv.corp.google.com
# Date 1244235210 25200
# Node ID cf2fd9253952b92e24b982f83ba1bc2faf584e8b
# Parent  aa0c48844632739a1efa8ff78f24ff4017fda89f
JVMTI does not execute post_resource_exhausted when allocating arrays close to Integer.MAX_VALUE.

diff -r aa0c48844632 -r cf2fd9253952 src/share/vm/gc_interface/collectedHeap.inline.hpp
--- a/src/share/vm/gc_interface/collectedHeap.inline.hpp	Thu May 14 10:57:58 2009 -0700
+++ b/src/share/vm/gc_interface/collectedHeap.inline.hpp	Fri Jun 05 13:53:30 2009 -0700
@@ -135,28 +135,14 @@ HeapWord* CollectedHeap::common_mem_allo
   }
 
 
-  if (!gc_overhead_limit_was_exceeded) {
-    // -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError support
-    report_java_out_of_memory("Java heap space");
-
-    if (JvmtiExport::should_post_resource_exhausted()) {
-      JvmtiExport::post_resource_exhausted(
-        JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_JAVA_HEAP,
-        "Java heap space");
-    }
-
-    THROW_OOP_0(Universe::out_of_memory_error_java_heap());
+ if (!gc_overhead_limit_was_exceeded) {
+    THROW_OOM("Java heap space",
+              JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_JAVA_HEAP,
+              Universe::out_of_memory_error_java_heap());
   } else {
-    // -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError support
-    report_java_out_of_memory("GC overhead limit exceeded");
-
-    if (JvmtiExport::should_post_resource_exhausted()) {
-      JvmtiExport::post_resource_exhausted(
-        JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_JAVA_HEAP,
-        "GC overhead limit exceeded");
-    }
-
-    THROW_OOP_0(Universe::out_of_memory_error_gc_overhead_limit());
+    THROW_OOM("GC overhead limit exceeded",
+              JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_JAVA_HEAP,
+              Universe::out_of_memory_error_gc_overhead_limit());
   }
 }
 
@@ -191,16 +177,10 @@ HeapWord* CollectedHeap::common_permanen
            "Unexpected exception, will result in uninitialized storage");
     return result;
   }
-  // -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError support
-  report_java_out_of_memory("PermGen space");
 
-  if (JvmtiExport::should_post_resource_exhausted()) {
-    JvmtiExport::post_resource_exhausted(
-        JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR,
-        "PermGen space");
-  }
-
-  THROW_OOP_0(Universe::out_of_memory_error_perm_gen());
+  THROW_OOM("PermGen space",
+            JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR,
+            Universe::out_of_memory_error_perm_gen());
 }
 
 HeapWord* CollectedHeap::common_permanent_mem_allocate_init(size_t size, TRAPS) {
diff -r aa0c48844632 -r cf2fd9253952 src/share/vm/oops/arrayKlass.cpp
--- a/src/share/vm/oops/arrayKlass.cpp	Thu May 14 10:57:58 2009 -0700
+++ b/src/share/vm/oops/arrayKlass.cpp	Fri Jun 05 13:53:30 2009 -0700
@@ -140,7 +140,10 @@ objArrayOop arrayKlass::allocate_arrayAr
     THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
   }
   if (length > arrayOopDesc::max_array_length(T_ARRAY)) {
-    THROW_OOP_0(Universe::out_of_memory_error_array_size());
+    THROW_OOM("Java heap space",
+              JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR |
+                  JVMTI_RESOURCE_EXHAUSTED_JAVA_HEAP,
+              Universe::out_of_memory_error_array_size());
   }
   int size = objArrayOopDesc::object_size(length);
   klassOop k = array_klass(n+dimension(), CHECK_0);
diff -r aa0c48844632 -r cf2fd9253952 src/share/vm/oops/instanceKlass.cpp
--- a/src/share/vm/oops/instanceKlass.cpp	Thu May 14 10:57:58 2009 -0700
+++ b/src/share/vm/oops/instanceKlass.cpp	Fri Jun 05 13:53:30 2009 -0700
@@ -497,7 +497,10 @@ objArrayOop instanceKlass::allocate_objA
 objArrayOop instanceKlass::allocate_objArray(int n, int length, TRAPS) {
   if (length < 0) THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
   if (length > arrayOopDesc::max_array_length(T_OBJECT)) {
-    THROW_OOP_0(Universe::out_of_memory_error_array_size());
+    THROW_OOM("Java heap space",
+              JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR |
+                  JVMTI_RESOURCE_EXHAUSTED_JAVA_HEAP,
+              Universe::out_of_memory_error_array_size());
   }
   int size = objArrayOopDesc::object_size(length);
   klassOop ak = array_klass(n, CHECK_NULL);
diff -r aa0c48844632 -r cf2fd9253952 src/share/vm/oops/objArrayKlass.cpp
--- a/src/share/vm/oops/objArrayKlass.cpp	Thu May 14 10:57:58 2009 -0700
+++ b/src/share/vm/oops/objArrayKlass.cpp	Fri Jun 05 13:53:30 2009 -0700
@@ -39,7 +39,10 @@ objArrayOop objArrayKlass::allocate(int 
       assert(a->is_parsable(), "Can't publish unless parsable");
       return a;
     } else {
-      THROW_OOP_0(Universe::out_of_memory_error_array_size());
+      THROW_OOM("Java heap space",
+                JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR |
+                    JVMTI_RESOURCE_EXHAUSTED_JAVA_HEAP,
+                Universe::out_of_memory_error_array_size());
     }
   } else {
     THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
diff -r aa0c48844632 -r cf2fd9253952 src/share/vm/oops/typeArrayKlass.cpp
--- a/src/share/vm/oops/typeArrayKlass.cpp	Thu May 14 10:57:58 2009 -0700
+++ b/src/share/vm/oops/typeArrayKlass.cpp	Fri Jun 05 13:53:30 2009 -0700
@@ -80,7 +80,10 @@ typeArrayOop typeArrayKlass::allocate(in
       assert(t->is_parsable(), "Don't publish unless parsable");
       return t;
     } else {
-      THROW_OOP_0(Universe::out_of_memory_error_array_size());
+      THROW_OOM("Java heap space",
+                JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR |
+                    JVMTI_RESOURCE_EXHAUSTED_JAVA_HEAP,
+                Universe::out_of_memory_error_array_size());
     }
   } else {
     THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
diff -r aa0c48844632 -r cf2fd9253952 src/share/vm/utilities/exceptions.hpp
--- a/src/share/vm/utilities/exceptions.hpp	Thu May 14 10:57:58 2009 -0700
+++ b/src/share/vm/utilities/exceptions.hpp	Fri Jun 05 13:53:30 2009 -0700
@@ -240,6 +240,15 @@ class Exceptions {
 #define THROW_NULL(name)                    THROW_(name, NULL)
 #define THROW_MSG_NULL(name, message)       THROW_MSG_(name, message, NULL)
 
+#define THROW_OOM(message, flags, exception)                    \
+  do {                                                          \
+    report_java_out_of_memory((message));                       \
+    if (JvmtiExport::should_post_resource_exhausted()) {        \
+      JvmtiExport::post_resource_exhausted((flags), (message)); \
+    }                                                           \
+    THROW_OOP_0((exception));                                   \
+  } while (0)
+
 // The CATCH macro checks that no exception has been thrown by a function; it is used at
 // call sites about which is statically known that the callee cannot throw an exception
 // even though it is declared with TRAPS.


More information about the hotspot-runtime-dev mailing list