< prev index next >

src/hotspot/share/runtime/jniHandles.cpp

Print this page

        

@@ -56,19 +56,19 @@
 
 jobject JNIHandles::make_local(oop obj) {
   return make_local(Thread::current(), obj);
 }
 
-
-jobject JNIHandles::make_local(Thread* thread, oop obj) {
+// Used by NewLocalRef which requires NULL on out-of-memory
+jobject JNIHandles::make_local(Thread* thread, oop obj, AllocFailType alloc_failmode) {
   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) {

@@ -100,11 +100,10 @@
   }
 
   return res;
 }
 
-
 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");
   jobject res = NULL;
   if (!obj.is_null()) {

@@ -341,11 +340,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 +358,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 +465,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 +513,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 >