< 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 >