< prev index next >

src/hotspot/share/runtime/jniHandles.cpp

Print this page

        

@@ -56,19 +56,32 @@
 
 jobject JNIHandles::make_local(oop obj) {
   return make_local(Thread::current(), obj);
 }
 
-
-jobject JNIHandles::make_local(Thread* thread, oop obj) {
+static int make_local_count = 0;
+static const int MAKE_LOCAL_MAX = 100;
+// Used by NewLocalRef which requires NULL on out-of-memory
+jobject JNIHandles::make_local(Thread* thread, oop obj, AllocFailType alloc_failmode) {
+  if (UseNewCode && alloc_failmode == AllocFailStrategy::RETURN_NULL) {
+    int tmp = ++make_local_count;
+    if (Verbose) tty->print_cr("COUNT: make_local = %d", tmp);
+    if (UseNewCode2) {
+      if (tmp >= MAKE_LOCAL_MAX) {
+        tty->print_cr("make_local returning NULL");
+        make_local_count = 0; // need to reset
+        return NULL;
+      }
+    }
+  }
   if (obj == NULL) {
     return NULL;                // ignore null handles
   } else {
     assert(oopDesc::is_oop(obj), "not an oop");
     assert(thread->is_Java_thread(), "not a Java thread");
     assert(!current_thread_in_native(), "must not be in native");
-    return thread->active_handles()->allocate_handle(obj);
+    return thread->active_handles()->allocate_handle(obj, alloc_failmode);
   }
 }
 
 static void report_handle_allocation_failure(AllocFailType alloc_failmode,
                                              const char* handle_kind) {

@@ -79,13 +92,27 @@
   } else {
     assert(alloc_failmode == AllocFailStrategy::RETURN_NULL, "invariant");
   }
 }
 
+static int make_global_count = 0;
+static const int MAKE_GLOBAL_MAX = 350;
+
 jobject JNIHandles::make_global(Handle obj, AllocFailType alloc_failmode) {
   assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC");
   assert(!current_thread_in_native(), "must not be in native");
+  if (UseNewCode) {
+    int tmp = ++make_global_count;
+    if (Verbose) tty->print_cr("COUNT: make_global = %d", tmp);
+    if (UseNewCode2 && alloc_failmode == AllocFailStrategy::RETURN_NULL) {
+      if (tmp >= MAKE_GLOBAL_MAX) {
+        tty->print_cr("make_global returning NULL");
+        make_global_count = 0; // need to reset
+        return NULL;
+      }
+    }
+  }
   jobject res = NULL;
   if (!obj.is_null()) {
     // ignore null handles
     assert(oopDesc::is_oop(obj()), "not an oop");
     oop* ptr = global_handles()->allocate();

@@ -100,14 +127,27 @@
   }
 
   return res;
 }
 
+static int make_weak_count = 0;
+static const int MAKE_WEAK_MAX = 90;
 
 jobject JNIHandles::make_weak_global(Handle obj, AllocFailType alloc_failmode) {
   assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC");
   assert(!current_thread_in_native(), "must not be in native");
+  if (UseNewCode) {
+    int tmp = ++make_weak_count;
+    if (Verbose) tty->print_cr("COUNT: make_weak = %d", tmp);
+    if (UseNewCode2 && alloc_failmode == AllocFailStrategy::RETURN_NULL) {
+      if (tmp >= MAKE_WEAK_MAX) {
+        tty->print_cr("make_weak returning NULL");
+        make_weak_count = 0; // need to reset
+        return NULL;
+      }
+    }
+  }
   jobject res = NULL;
   if (!obj.is_null()) {
     // ignore null handles
     assert(oopDesc::is_oop(obj()), "not an oop");
     oop* ptr = weak_global_handles()->allocate();

@@ -341,11 +381,11 @@
     _handles[index] = 0;
   }
 }
 #endif // ASSERT
 
-JNIHandleBlock* JNIHandleBlock::allocate_block(Thread* thread)  {
+JNIHandleBlock* JNIHandleBlock::allocate_block(Thread* thread, AllocFailType alloc_failmode)  {
   assert(thread == NULL || thread == Thread::current(), "sanity check");
   JNIHandleBlock* block;
   // Check the thread-local free list for a block so we don't
   // have to acquire a mutex.
   if (thread != NULL && thread->free_handle_block() != NULL) {

@@ -359,11 +399,18 @@
     //   JNIHandleBlockFreeList_lock (JNIHandleBlock::allocate_block)
     MutexLocker ml(JNIHandleBlockFreeList_lock,
                    Mutex::_no_safepoint_check_flag);
     if (_block_free_list == NULL) {
       // Allocate new block
+      if (alloc_failmode == AllocFailStrategy::RETURN_NULL) {
+        block = new (std::nothrow) JNIHandleBlock();
+        if (block == NULL) {
+          return NULL;
+        }
+      } else {
       block = new JNIHandleBlock();
+      }
       _blocks_allocated++;
       block->zap();
       #ifndef PRODUCT
       // Link new block to list of all allocated blocks
       block->_block_list_link = _block_list;

@@ -459,11 +506,11 @@
     current_chain = current_chain->pop_frame_link();
   }
 }
 
 
-jobject JNIHandleBlock::allocate_handle(oop obj) {
+jobject JNIHandleBlock::allocate_handle(oop obj, AllocFailType alloc_failmode) {
   assert(Universe::heap()->is_in(obj), "sanity check");
   if (_top == 0) {
     // This is the first allocation or the initial block got zapped when
     // entering a native function. If we have any following blocks they are
     // not valid anymore.

@@ -507,27 +554,30 @@
   }
   // Check if unused block follow last
   if (_last->_next != NULL) {
     // update last and retry
     _last = _last->_next;
-    return allocate_handle(obj);
+    return allocate_handle(obj, alloc_failmode);
   }
 
   // No space available, we have to rebuild free list or expand
   if (_allocate_before_rebuild == 0) {
       rebuild_free_list();        // updates _allocate_before_rebuild counter
   } else {
     // Append new block
     Thread* thread = Thread::current();
     Handle obj_handle(thread, obj);
     // This can block, so we need to preserve obj across call.
-    _last->_next = JNIHandleBlock::allocate_block(thread);
+    _last->_next = JNIHandleBlock::allocate_block(thread, alloc_failmode);
+    if (_last->_next == NULL) {
+      return NULL;
+    }
     _last = _last->_next;
     _allocate_before_rebuild--;
     obj = obj_handle();
   }
-  return allocate_handle(obj);  // retry
+  return allocate_handle(obj, alloc_failmode);  // retry
 }
 
 void JNIHandleBlock::rebuild_free_list() {
   assert(_allocate_before_rebuild == 0 && _free_list == NULL, "just checking");
   int free = 0;
< prev index next >