inline oop JNIHandles::resolve_non_null(jobject handle){ assert(handle != NULL, "JNI handle should not be null"); oop result = *(oop*)handle; assert(result != NULL, "Invalid value read from jni handle"); assert(result != badJNIHandle, "Pointing to zapped jni handle area"); // Don't let that private _deleted_handle object escape into the wild. assert(result != deleted_handle(), "Used a deleted global handle."); return result; };
debug_only(StableMemoryChecker smc(name, len * sizeof(name[0]))); assert(!Universe::heap()->is_in_reserved(name), "proposed name of symbol must be stable");
#if INCLUDE_ALL_GCS if (G1StringDedup::is_enabled()) { // Deduplicate the string before it is interned. Note that we should never // deduplicate a string after it has been interned. Doing so will counteract // compiler optimizations done on e.g. interned string literals. G1StringDedup::deduplicate(string()); } #endif
jobject JNIHandles::make_local(JNIEnv* env, oop obj){ if (obj == NULL) { returnNULL; // ignore null handles } else { JavaThread* thread = JavaThread::thread_from_jni_environment(env); // 确保obj指向的是堆上的保留区域(the reserved area of the heap) assert(Universe::heap()->is_in_reserved(obj), "sanity check"); return thread->active_handles()->allocate_handle(obj); } }
jobject JNIHandleBlock::allocate_handle(oop obj){ assert(Universe::heap()->is_in_reserved(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. for (JNIHandleBlock* current = _next; current != NULL; current = current->_next) { assert(current->_last == NULL, "only first block should have _last set"); assert(current->_free_list == NULL, "only first block should have _free_list set"); current->_top = 0; if (ZapJNIHandleArea) current->zap(); } // Clear initial block _free_list = NULL; _allocate_before_rebuild = 0; _last = this; if (ZapJNIHandleArea) zap(); }
// Try last block if (_last->_top < block_size_in_oops) { oop* handle = &(_last->_handles)[_last->_top++]; *handle = obj; return (jobject) handle; }
// Try free list if (_free_list != NULL) { oop* handle = _free_list; _free_list = (oop*) *_free_list; *handle = obj; return (jobject) handle; } // Check if unused block follow last if (_last->_next != NULL) { // update last and retry _last = _last->_next; returnallocate_handle(obj); }
// 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 accross call. _last->_next = JNIHandleBlock::allocate_block(thread); _last = _last->_next; _allocate_before_rebuild--; obj = obj_handle(); } returnallocate_handle(obj); // retry }