mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-18 18:14:38 +02:00
8276658: Clean up JNI local handles code
Reviewed-by: dholmes, pchilanomate
This commit is contained in:
parent
aeba653034
commit
3b2585c02b
25 changed files with 123 additions and 350 deletions
|
@ -87,7 +87,7 @@ ciInstanceKlass::ciInstanceKlass(Klass* k) :
|
||||||
(void)CURRENT_ENV->get_object(holder);
|
(void)CURRENT_ENV->get_object(holder);
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread *thread = Thread::current();
|
JavaThread *thread = JavaThread::current();
|
||||||
if (ciObjectFactory::is_initialized()) {
|
if (ciObjectFactory::is_initialized()) {
|
||||||
_loader = JNIHandles::make_local(thread, ik->class_loader());
|
_loader = JNIHandles::make_local(thread, ik->class_loader());
|
||||||
_protection_domain = JNIHandles::make_local(thread,
|
_protection_domain = JNIHandles::make_local(thread,
|
||||||
|
|
|
@ -2200,7 +2200,7 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate a new set of JNI handles.
|
// Allocate a new set of JNI handles.
|
||||||
push_jni_handle_block();
|
JNIHandleMark jhm(thread);
|
||||||
Method* target_handle = task->method();
|
Method* target_handle = task->method();
|
||||||
int compilable = ciEnv::MethodCompilable;
|
int compilable = ciEnv::MethodCompilable;
|
||||||
const char* failure_reason = NULL;
|
const char* failure_reason = NULL;
|
||||||
|
@ -2319,9 +2319,6 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
|
||||||
post_compilation_event(event, task);
|
post_compilation_event(event, task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Remove the JNI handle block after the ciEnv destructor has run in
|
|
||||||
// the previous block.
|
|
||||||
pop_jni_handle_block();
|
|
||||||
|
|
||||||
if (failure_reason != NULL) {
|
if (failure_reason != NULL) {
|
||||||
task->set_failure_reason(failure_reason, failure_reason_on_C_heap);
|
task->set_failure_reason(failure_reason, failure_reason_on_C_heap);
|
||||||
|
@ -2482,38 +2479,6 @@ void CompileBroker::update_compile_perf_data(CompilerThread* thread, const metho
|
||||||
counters->set_compile_type((jlong) last_compile_type);
|
counters->set_compile_type((jlong) last_compile_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
|
||||||
// CompileBroker::push_jni_handle_block
|
|
||||||
//
|
|
||||||
// Push on a new block of JNI handles.
|
|
||||||
void CompileBroker::push_jni_handle_block() {
|
|
||||||
JavaThread* thread = JavaThread::current();
|
|
||||||
|
|
||||||
// Allocate a new block for JNI handles.
|
|
||||||
// Inlined code from jni_PushLocalFrame()
|
|
||||||
JNIHandleBlock* java_handles = thread->active_handles();
|
|
||||||
JNIHandleBlock* compile_handles = JNIHandleBlock::allocate_block(thread);
|
|
||||||
assert(compile_handles != NULL && java_handles != NULL, "should not be NULL");
|
|
||||||
compile_handles->set_pop_frame_link(java_handles); // make sure java handles get gc'd.
|
|
||||||
thread->set_active_handles(compile_handles);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
|
||||||
// CompileBroker::pop_jni_handle_block
|
|
||||||
//
|
|
||||||
// Pop off the current block of JNI handles.
|
|
||||||
void CompileBroker::pop_jni_handle_block() {
|
|
||||||
JavaThread* thread = JavaThread::current();
|
|
||||||
|
|
||||||
// Release our JNI handle block
|
|
||||||
JNIHandleBlock* compile_handles = thread->active_handles();
|
|
||||||
JNIHandleBlock* java_handles = compile_handles->pop_frame_link();
|
|
||||||
thread->set_active_handles(java_handles);
|
|
||||||
compile_handles->set_pop_frame_link(NULL);
|
|
||||||
JNIHandleBlock::release_block(compile_handles, thread); // may block
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// CompileBroker::collect_statistics
|
// CompileBroker::collect_statistics
|
||||||
//
|
//
|
||||||
|
|
|
@ -259,8 +259,6 @@ class CompileBroker: AllStatic {
|
||||||
int compilable, const char* failure_reason);
|
int compilable, const char* failure_reason);
|
||||||
static void update_compile_perf_data(CompilerThread *thread, const methodHandle& method, bool is_osr);
|
static void update_compile_perf_data(CompilerThread *thread, const methodHandle& method, bool is_osr);
|
||||||
|
|
||||||
static void push_jni_handle_block();
|
|
||||||
static void pop_jni_handle_block();
|
|
||||||
static void collect_statistics(CompilerThread* thread, elapsedTimer time, CompileTask* task);
|
static void collect_statistics(CompilerThread* thread, elapsedTimer time, CompileTask* task);
|
||||||
|
|
||||||
static void compile_method_base(const methodHandle& method,
|
static void compile_method_base(const methodHandle& method,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -42,9 +42,6 @@ void ConcurrentGCThread::create_and_start(ThreadPriority prio) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConcurrentGCThread::run() {
|
void ConcurrentGCThread::run() {
|
||||||
// Setup handle area
|
|
||||||
set_active_handles(JNIHandleBlock::allocate_block());
|
|
||||||
|
|
||||||
// Wait for initialization to complete
|
// Wait for initialization to complete
|
||||||
wait_init_completed();
|
wait_init_completed();
|
||||||
|
|
||||||
|
|
|
@ -55,53 +55,6 @@ bool register_jfr_dcmds() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// JNIHandle management
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
|
||||||
// push_jni_handle_block
|
|
||||||
//
|
|
||||||
// Push on a new block of JNI handles.
|
|
||||||
static void push_jni_handle_block(JavaThread* const thread) {
|
|
||||||
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(thread));
|
|
||||||
|
|
||||||
// Allocate a new block for JNI handles.
|
|
||||||
// Inlined code from jni_PushLocalFrame()
|
|
||||||
JNIHandleBlock* prev_handles = thread->active_handles();
|
|
||||||
JNIHandleBlock* entry_handles = JNIHandleBlock::allocate_block(thread);
|
|
||||||
assert(entry_handles != NULL && prev_handles != NULL, "should not be NULL");
|
|
||||||
entry_handles->set_pop_frame_link(prev_handles); // make sure prev handles get gc'd.
|
|
||||||
thread->set_active_handles(entry_handles);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
|
||||||
// pop_jni_handle_block
|
|
||||||
//
|
|
||||||
// Pop off the current block of JNI handles.
|
|
||||||
static void pop_jni_handle_block(JavaThread* const thread) {
|
|
||||||
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(thread));
|
|
||||||
|
|
||||||
// Release our JNI handle block
|
|
||||||
JNIHandleBlock* entry_handles = thread->active_handles();
|
|
||||||
JNIHandleBlock* prev_handles = entry_handles->pop_frame_link();
|
|
||||||
// restore
|
|
||||||
thread->set_active_handles(prev_handles);
|
|
||||||
entry_handles->set_pop_frame_link(NULL);
|
|
||||||
JNIHandleBlock::release_block(entry_handles, thread); // may block
|
|
||||||
}
|
|
||||||
|
|
||||||
class JNIHandleBlockManager : public StackObj {
|
|
||||||
private:
|
|
||||||
JavaThread* const _thread;
|
|
||||||
public:
|
|
||||||
JNIHandleBlockManager(JavaThread* thread) : _thread(thread) {
|
|
||||||
push_jni_handle_block(_thread);
|
|
||||||
}
|
|
||||||
|
|
||||||
~JNIHandleBlockManager() {
|
|
||||||
pop_jni_handle_block(_thread);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static bool is_module_available(outputStream* output, TRAPS) {
|
static bool is_module_available(outputStream* output, TRAPS) {
|
||||||
return JfrJavaSupport::is_jdk_jfr_module_available(output, THREAD);
|
return JfrJavaSupport::is_jdk_jfr_module_available(output, THREAD);
|
||||||
}
|
}
|
||||||
|
@ -223,7 +176,7 @@ void JfrDCmd::invoke(JfrJavaArguments& method, TRAPS) const {
|
||||||
constructor_args.set_klass(javaClass(), CHECK);
|
constructor_args.set_klass(javaClass(), CHECK);
|
||||||
|
|
||||||
HandleMark hm(THREAD);
|
HandleMark hm(THREAD);
|
||||||
JNIHandleBlockManager jni_handle_management(THREAD);
|
JNIHandleMark jni_handle_management(THREAD);
|
||||||
|
|
||||||
const oop dcmd = construct_dcmd_instance(&constructor_args, CHECK);
|
const oop dcmd = construct_dcmd_instance(&constructor_args, CHECK);
|
||||||
|
|
||||||
|
@ -494,7 +447,7 @@ void JfrConfigureFlightRecorderDCmd::execute(DCmdSource source, TRAPS) {
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleMark hm(THREAD);
|
HandleMark hm(THREAD);
|
||||||
JNIHandleBlockManager jni_handle_management(THREAD);
|
JNIHandleMark jni_handle_management(THREAD);
|
||||||
|
|
||||||
JavaValue result(T_OBJECT);
|
JavaValue result(T_OBJECT);
|
||||||
JfrJavaArguments constructor_args(&result);
|
JfrJavaArguments constructor_args(&result);
|
||||||
|
|
|
@ -71,7 +71,7 @@ static void check_new_unstarted_java_thread(JavaThread* t) {
|
||||||
*/
|
*/
|
||||||
jobject JfrJavaSupport::local_jni_handle(const oop obj, JavaThread* t) {
|
jobject JfrJavaSupport::local_jni_handle(const oop obj, JavaThread* t) {
|
||||||
DEBUG_ONLY(check_java_thread_in_vm(t));
|
DEBUG_ONLY(check_java_thread_in_vm(t));
|
||||||
return t->active_handles()->allocate_handle(obj);
|
return t->active_handles()->allocate_handle(t, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
jobject JfrJavaSupport::local_jni_handle(const jobject handle, JavaThread* t) {
|
jobject JfrJavaSupport::local_jni_handle(const jobject handle, JavaThread* t) {
|
||||||
|
|
|
@ -899,7 +899,7 @@ GrowableArray<ScopeValue*>* CodeInstaller::record_virtual_objects(JVMCIObject de
|
||||||
}
|
}
|
||||||
Klass* klass = jvmci_env()->asKlass(type);
|
Klass* klass = jvmci_env()->asKlass(type);
|
||||||
oop javaMirror = klass->java_mirror();
|
oop javaMirror = klass->java_mirror();
|
||||||
ScopeValue *klass_sv = new ConstantOopWriteValue(JNIHandles::make_local(Thread::current(), javaMirror));
|
ScopeValue *klass_sv = new ConstantOopWriteValue(JNIHandles::make_local(javaMirror));
|
||||||
ObjectValue* sv = is_auto_box ? new AutoBoxObjectValue(id, klass_sv) : new ObjectValue(id, klass_sv);
|
ObjectValue* sv = is_auto_box ? new AutoBoxObjectValue(id, klass_sv) : new ObjectValue(id, klass_sv);
|
||||||
if (id < 0 || id >= objects->length()) {
|
if (id < 0 || id >= objects->length()) {
|
||||||
JVMCI_ERROR_NULL("virtual object id %d out of bounds", id);
|
JVMCI_ERROR_NULL("virtual object id %d out of bounds", id);
|
||||||
|
|
|
@ -86,29 +86,6 @@ static void requireInHotSpot(const char* caller, JVMCI_TRAPS) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JNIHandleMark::push_jni_handle_block(JavaThread* thread) {
|
|
||||||
if (thread != NULL) {
|
|
||||||
// Allocate a new block for JNI handles.
|
|
||||||
// Inlined code from jni_PushLocalFrame()
|
|
||||||
JNIHandleBlock* java_handles = thread->active_handles();
|
|
||||||
JNIHandleBlock* compile_handles = JNIHandleBlock::allocate_block(thread);
|
|
||||||
assert(compile_handles != NULL && java_handles != NULL, "should not be NULL");
|
|
||||||
compile_handles->set_pop_frame_link(java_handles);
|
|
||||||
thread->set_active_handles(compile_handles);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void JNIHandleMark::pop_jni_handle_block(JavaThread* thread) {
|
|
||||||
if (thread != NULL) {
|
|
||||||
// Release our JNI handle block
|
|
||||||
JNIHandleBlock* compile_handles = thread->active_handles();
|
|
||||||
JNIHandleBlock* java_handles = compile_handles->pop_frame_link();
|
|
||||||
thread->set_active_handles(java_handles);
|
|
||||||
compile_handles->set_pop_frame_link(NULL);
|
|
||||||
JNIHandleBlock::release_block(compile_handles, thread); // may block
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class JVMCITraceMark : public StackObj {
|
class JVMCITraceMark : public StackObj {
|
||||||
const char* _msg;
|
const char* _msg;
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -173,15 +173,4 @@ class JavaArgumentUnboxer : public SignatureIterator {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class JNIHandleMark : public StackObj {
|
|
||||||
JavaThread* _thread;
|
|
||||||
public:
|
|
||||||
JNIHandleMark(JavaThread* thread) : _thread(thread) { push_jni_handle_block(thread); }
|
|
||||||
~JNIHandleMark() { pop_jni_handle_block(_thread); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
static void push_jni_handle_block(JavaThread* thread);
|
|
||||||
static void pop_jni_handle_block(JavaThread* thread);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // SHARE_JVMCI_JVMCICOMPILERTOVM_HPP
|
#endif // SHARE_JVMCI_JVMCICOMPILERTOVM_HPP
|
||||||
|
|
|
@ -639,11 +639,8 @@ JNI_ENTRY(jint, jni_PushLocalFrame(JNIEnv *env, jint capacity))
|
||||||
HOTSPOT_JNI_PUSHLOCALFRAME_RETURN((uint32_t)JNI_ERR);
|
HOTSPOT_JNI_PUSHLOCALFRAME_RETURN((uint32_t)JNI_ERR);
|
||||||
return JNI_ERR;
|
return JNI_ERR;
|
||||||
}
|
}
|
||||||
JNIHandleBlock* old_handles = thread->active_handles();
|
|
||||||
JNIHandleBlock* new_handles = JNIHandleBlock::allocate_block(thread);
|
thread->push_jni_handle_block();
|
||||||
assert(new_handles != NULL, "should not be NULL");
|
|
||||||
new_handles->set_pop_frame_link(old_handles);
|
|
||||||
thread->set_active_handles(new_handles);
|
|
||||||
jint ret = JNI_OK;
|
jint ret = JNI_OK;
|
||||||
HOTSPOT_JNI_PUSHLOCALFRAME_RETURN(ret);
|
HOTSPOT_JNI_PUSHLOCALFRAME_RETURN(ret);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -1510,7 +1510,7 @@ JvmtiModuleClosure::get_all_modules(JvmtiEnv* env, jint* module_count_ptr, jobje
|
||||||
return JVMTI_ERROR_OUT_OF_MEMORY;
|
return JVMTI_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
for (jint idx = 0; idx < len; idx++) {
|
for (jint idx = 0; idx < len; idx++) {
|
||||||
array[idx] = JNIHandles::make_local(Thread::current(), _tbl->at(idx).resolve());
|
array[idx] = JNIHandles::make_local(_tbl->at(idx).resolve());
|
||||||
}
|
}
|
||||||
_tbl = NULL;
|
_tbl = NULL;
|
||||||
*modules_ptr = array;
|
*modules_ptr = array;
|
||||||
|
|
|
@ -141,20 +141,11 @@ private:
|
||||||
JavaThread *_thread;
|
JavaThread *_thread;
|
||||||
JNIEnv* _jni_env;
|
JNIEnv* _jni_env;
|
||||||
JvmtiThreadState::ExceptionState _saved_exception_state;
|
JvmtiThreadState::ExceptionState _saved_exception_state;
|
||||||
#if 0
|
|
||||||
JNIHandleBlock* _hblock;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JvmtiEventMark(JavaThread *thread) : _thread(thread),
|
JvmtiEventMark(JavaThread *thread) : _thread(thread),
|
||||||
_jni_env(thread->jni_environment()),
|
_jni_env(thread->jni_environment()),
|
||||||
_saved_exception_state(JvmtiThreadState::ES_CLEARED) {
|
_saved_exception_state(JvmtiThreadState::ES_CLEARED) {
|
||||||
#if 0
|
|
||||||
_hblock = thread->active_handles();
|
|
||||||
_hblock->clear_thoroughly(); // so we can be safe
|
|
||||||
#else
|
|
||||||
// we want to use the code above - but that needs the JNIHandle changes - later...
|
|
||||||
// for now, steal JNI push local frame code
|
|
||||||
JvmtiThreadState *state = thread->jvmti_thread_state();
|
JvmtiThreadState *state = thread->jvmti_thread_state();
|
||||||
// we are before an event.
|
// we are before an event.
|
||||||
// Save current jvmti thread exception state.
|
// Save current jvmti thread exception state.
|
||||||
|
@ -162,31 +153,13 @@ public:
|
||||||
_saved_exception_state = state->get_exception_state();
|
_saved_exception_state = state->get_exception_state();
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIHandleBlock* old_handles = thread->active_handles();
|
thread->push_jni_handle_block();
|
||||||
JNIHandleBlock* new_handles = JNIHandleBlock::allocate_block(thread);
|
|
||||||
assert(new_handles != NULL, "should not be NULL");
|
|
||||||
new_handles->set_pop_frame_link(old_handles);
|
|
||||||
thread->set_active_handles(new_handles);
|
|
||||||
#endif
|
|
||||||
assert(thread == JavaThread::current(), "thread must be current!");
|
assert(thread == JavaThread::current(), "thread must be current!");
|
||||||
thread->frame_anchor()->make_walkable(thread);
|
thread->frame_anchor()->make_walkable(thread);
|
||||||
};
|
};
|
||||||
|
|
||||||
~JvmtiEventMark() {
|
~JvmtiEventMark() {
|
||||||
#if 0
|
_thread->pop_jni_handle_block();
|
||||||
_hblock->clear(); // for consistency with future correct behavior
|
|
||||||
#else
|
|
||||||
// we want to use the code above - but that needs the JNIHandle changes - later...
|
|
||||||
// for now, steal JNI pop local frame code
|
|
||||||
JNIHandleBlock* old_handles = _thread->active_handles();
|
|
||||||
JNIHandleBlock* new_handles = old_handles->pop_frame_link();
|
|
||||||
assert(new_handles != NULL, "should not be NULL");
|
|
||||||
_thread->set_active_handles(new_handles);
|
|
||||||
// Note that we set the pop_frame_link to NULL explicitly, otherwise
|
|
||||||
// the release_block call will release the blocks.
|
|
||||||
old_handles->set_pop_frame_link(NULL);
|
|
||||||
JNIHandleBlock::release_block(old_handles, _thread); // may block
|
|
||||||
#endif
|
|
||||||
|
|
||||||
JvmtiThreadState* state = _thread->jvmti_thread_state();
|
JvmtiThreadState* state = _thread->jvmti_thread_state();
|
||||||
// we are continuing after an event.
|
// we are continuing after an event.
|
||||||
|
@ -196,13 +169,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
jobject to_jobject(oop obj) { return obj == NULL? NULL : _hblock->allocate_handle_fast(obj); }
|
|
||||||
#else
|
|
||||||
// we want to use the code above - but that needs the JNIHandle changes - later...
|
|
||||||
// for now, use regular make_local
|
|
||||||
jobject to_jobject(oop obj) { return JNIHandles::make_local(_thread,obj); }
|
jobject to_jobject(oop obj) { return JNIHandles::make_local(_thread,obj); }
|
||||||
#endif
|
|
||||||
|
|
||||||
jclass to_jclass(Klass* klass) { return (klass == NULL ? NULL : (jclass)to_jobject(klass->java_mirror())); }
|
jclass to_jclass(Klass* klass) { return (klass == NULL ? NULL : (jclass)to_jobject(klass->java_mirror())); }
|
||||||
|
|
||||||
|
|
|
@ -56,18 +56,17 @@ void jni_handles_init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
jobject JNIHandles::make_local(oop obj) {
|
jobject JNIHandles::make_local(oop obj) {
|
||||||
return make_local(Thread::current(), obj);
|
return make_local(JavaThread::current(), obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used by NewLocalRef which requires NULL on out-of-memory
|
// Used by NewLocalRef which requires NULL on out-of-memory
|
||||||
jobject JNIHandles::make_local(Thread* thread, oop obj, AllocFailType alloc_failmode) {
|
jobject JNIHandles::make_local(JavaThread* thread, oop obj, AllocFailType alloc_failmode) {
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
return NULL; // ignore null handles
|
return NULL; // ignore null handles
|
||||||
} else {
|
} else {
|
||||||
assert(oopDesc::is_oop(obj), "not an oop");
|
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");
|
assert(!current_thread_in_native(), "must not be in native");
|
||||||
return thread->active_handles()->allocate_handle(obj, alloc_failmode);
|
return thread->active_handles()->allocate_handle(thread, obj, alloc_failmode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +186,7 @@ inline bool is_storage_handle(const OopStorage* storage, const oop* ptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
jobjectRefType JNIHandles::handle_type(Thread* thread, jobject handle) {
|
jobjectRefType JNIHandles::handle_type(JavaThread* thread, jobject handle) {
|
||||||
assert(handle != NULL, "precondition");
|
assert(handle != NULL, "precondition");
|
||||||
jobjectRefType result = JNIInvalidRefType;
|
jobjectRefType result = JNIInvalidRefType;
|
||||||
if (is_jweak(handle)) {
|
if (is_jweak(handle)) {
|
||||||
|
@ -205,9 +204,7 @@ jobjectRefType JNIHandles::handle_type(Thread* thread, jobject handle) {
|
||||||
|
|
||||||
case OopStorage::INVALID_ENTRY:
|
case OopStorage::INVALID_ENTRY:
|
||||||
// Not in global storage. Might be a local handle.
|
// Not in global storage. Might be a local handle.
|
||||||
if (is_local_handle(thread, handle) ||
|
if (is_local_handle(thread, handle) || is_frame_handle(thread, handle)) {
|
||||||
(thread->is_Java_thread() &&
|
|
||||||
is_frame_handle(JavaThread::cast(thread), handle))) {
|
|
||||||
result = JNILocalRefType;
|
result = JNILocalRefType;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -220,7 +217,7 @@ jobjectRefType JNIHandles::handle_type(Thread* thread, jobject handle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool JNIHandles::is_local_handle(Thread* thread, jobject handle) {
|
bool JNIHandles::is_local_handle(JavaThread* thread, jobject handle) {
|
||||||
assert(handle != NULL, "precondition");
|
assert(handle != NULL, "precondition");
|
||||||
JNIHandleBlock* block = thread->active_handles();
|
JNIHandleBlock* block = thread->active_handles();
|
||||||
|
|
||||||
|
@ -305,12 +302,7 @@ bool JNIHandles::current_thread_in_native() {
|
||||||
JavaThread::cast(thread)->thread_state() == _thread_in_native);
|
JavaThread::cast(thread)->thread_state() == _thread_in_native);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int JNIHandleBlock::_blocks_allocated = 0;
|
int JNIHandleBlock::_blocks_allocated = 0;
|
||||||
JNIHandleBlock* JNIHandleBlock::_block_free_list = NULL;
|
|
||||||
#ifndef PRODUCT
|
|
||||||
JNIHandleBlock* JNIHandleBlock::_block_list = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static inline bool is_tagged_free_list(uintptr_t value) {
|
static inline bool is_tagged_free_list(uintptr_t value) {
|
||||||
return (value & 1u) != 0;
|
return (value & 1u) != 0;
|
||||||
|
@ -343,23 +335,17 @@ void JNIHandleBlock::zap() {
|
||||||
}
|
}
|
||||||
#endif // ASSERT
|
#endif // ASSERT
|
||||||
|
|
||||||
JNIHandleBlock* JNIHandleBlock::allocate_block(Thread* thread, AllocFailType alloc_failmode) {
|
JNIHandleBlock* JNIHandleBlock::allocate_block(JavaThread* thread, AllocFailType alloc_failmode) {
|
||||||
assert(thread == NULL || thread == Thread::current(), "sanity check");
|
// The VM thread can allocate a handle block in behalf of another thread during a safepoint.
|
||||||
|
assert(thread == NULL || thread == Thread::current() || SafepointSynchronize::is_at_safepoint(),
|
||||||
|
"sanity check");
|
||||||
JNIHandleBlock* block;
|
JNIHandleBlock* block;
|
||||||
// Check the thread-local free list for a block so we don't
|
// Check the thread-local free list for a block so we don't
|
||||||
// have to acquire a mutex.
|
// have to acquire a mutex.
|
||||||
if (thread != NULL && thread->free_handle_block() != NULL) {
|
if (thread != NULL && thread->free_handle_block() != NULL) {
|
||||||
block = thread->free_handle_block();
|
block = thread->free_handle_block();
|
||||||
thread->set_free_handle_block(block->_next);
|
thread->set_free_handle_block(block->_next);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// locking with safepoint checking introduces a potential deadlock:
|
|
||||||
// - we would hold JNIHandleBlockFreeList_lock and then Threads_lock
|
|
||||||
// - another would hold Threads_lock (jni_AttachCurrentThread) and then
|
|
||||||
// JNIHandleBlockFreeList_lock (JNIHandleBlock::allocate_block)
|
|
||||||
MutexLocker ml(JNIHandleBlockFreeList_lock,
|
|
||||||
Mutex::_no_safepoint_check_flag);
|
|
||||||
if (_block_free_list == NULL) {
|
|
||||||
// Allocate new block
|
// Allocate new block
|
||||||
if (alloc_failmode == AllocFailStrategy::RETURN_NULL) {
|
if (alloc_failmode == AllocFailStrategy::RETURN_NULL) {
|
||||||
block = new (std::nothrow) JNIHandleBlock();
|
block = new (std::nothrow) JNIHandleBlock();
|
||||||
|
@ -369,18 +355,8 @@ JNIHandleBlock* JNIHandleBlock::allocate_block(Thread* thread, AllocFailType all
|
||||||
} else {
|
} else {
|
||||||
block = new JNIHandleBlock();
|
block = new JNIHandleBlock();
|
||||||
}
|
}
|
||||||
_blocks_allocated++;
|
Atomic::inc(&_blocks_allocated);
|
||||||
block->zap();
|
block->zap();
|
||||||
#ifndef PRODUCT
|
|
||||||
// Link new block to list of all allocated blocks
|
|
||||||
block->_block_list_link = _block_list;
|
|
||||||
_block_list = block;
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
// Get block from free list
|
|
||||||
block = _block_free_list;
|
|
||||||
_block_free_list = _block_free_list->_next;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
block->_top = 0;
|
block->_top = 0;
|
||||||
block->_next = NULL;
|
block->_next = NULL;
|
||||||
|
@ -394,7 +370,7 @@ JNIHandleBlock* JNIHandleBlock::allocate_block(Thread* thread, AllocFailType all
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void JNIHandleBlock::release_block(JNIHandleBlock* block, Thread* thread) {
|
void JNIHandleBlock::release_block(JNIHandleBlock* block, JavaThread* thread) {
|
||||||
assert(thread == NULL || thread == Thread::current(), "sanity check");
|
assert(thread == NULL || thread == Thread::current(), "sanity check");
|
||||||
JNIHandleBlock* pop_frame_link = block->pop_frame_link();
|
JNIHandleBlock* pop_frame_link = block->pop_frame_link();
|
||||||
// Put returned block at the beginning of the thread-local free list.
|
// Put returned block at the beginning of the thread-local free list.
|
||||||
|
@ -415,20 +391,8 @@ void JNIHandleBlock::release_block(JNIHandleBlock* block, Thread* thread) {
|
||||||
block = NULL;
|
block = NULL;
|
||||||
}
|
}
|
||||||
if (block != NULL) {
|
if (block != NULL) {
|
||||||
// Return blocks to free list
|
Atomic::dec(&_blocks_allocated);
|
||||||
// locking with safepoint checking introduces a potential deadlock:
|
delete block;
|
||||||
// - we would hold JNIHandleBlockFreeList_lock and then Threads_lock
|
|
||||||
// - another would hold Threads_lock (jni_AttachCurrentThread) and then
|
|
||||||
// JNIHandleBlockFreeList_lock (JNIHandleBlock::allocate_block)
|
|
||||||
MutexLocker ml(JNIHandleBlockFreeList_lock,
|
|
||||||
Mutex::_no_safepoint_check_flag);
|
|
||||||
while (block != NULL) {
|
|
||||||
block->zap();
|
|
||||||
JNIHandleBlock* next = block->_next;
|
|
||||||
block->_next = _block_free_list;
|
|
||||||
_block_free_list = block;
|
|
||||||
block = next;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (pop_frame_link != NULL) {
|
if (pop_frame_link != NULL) {
|
||||||
// As a sanity check we release blocks pointed to by the pop_frame_link.
|
// As a sanity check we release blocks pointed to by the pop_frame_link.
|
||||||
|
@ -468,7 +432,7 @@ void JNIHandleBlock::oops_do(OopClosure* f) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
jobject JNIHandleBlock::allocate_handle(oop obj, AllocFailType alloc_failmode) {
|
jobject JNIHandleBlock::allocate_handle(JavaThread* caller, oop obj, AllocFailType alloc_failmode) {
|
||||||
assert(Universe::heap()->is_in(obj), "sanity check");
|
assert(Universe::heap()->is_in(obj), "sanity check");
|
||||||
if (_top == 0) {
|
if (_top == 0) {
|
||||||
// This is the first allocation or the initial block got zapped when
|
// This is the first allocation or the initial block got zapped when
|
||||||
|
@ -516,26 +480,21 @@ jobject JNIHandleBlock::allocate_handle(oop obj, AllocFailType alloc_failmode) {
|
||||||
if (_last->_next != NULL) {
|
if (_last->_next != NULL) {
|
||||||
// update last and retry
|
// update last and retry
|
||||||
_last = _last->_next;
|
_last = _last->_next;
|
||||||
return allocate_handle(obj, alloc_failmode);
|
return allocate_handle(caller, obj, alloc_failmode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// No space available, we have to rebuild free list or expand
|
// No space available, we have to rebuild free list or expand
|
||||||
if (_allocate_before_rebuild == 0) {
|
if (_allocate_before_rebuild == 0) {
|
||||||
rebuild_free_list(); // updates _allocate_before_rebuild counter
|
rebuild_free_list(); // updates _allocate_before_rebuild counter
|
||||||
} else {
|
} else {
|
||||||
// Append new block
|
_last->_next = JNIHandleBlock::allocate_block(caller, alloc_failmode);
|
||||||
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, alloc_failmode);
|
|
||||||
if (_last->_next == NULL) {
|
if (_last->_next == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
_last = _last->_next;
|
_last = _last->_next;
|
||||||
_allocate_before_rebuild--;
|
_allocate_before_rebuild--;
|
||||||
obj = obj_handle();
|
|
||||||
}
|
}
|
||||||
return allocate_handle(obj, alloc_failmode); // retry
|
return allocate_handle(caller, obj, alloc_failmode); // retry
|
||||||
}
|
}
|
||||||
|
|
||||||
void JNIHandleBlock::rebuild_free_list() {
|
void JNIHandleBlock::rebuild_free_list() {
|
||||||
|
@ -612,46 +571,3 @@ const size_t JNIHandleBlock::get_number_of_live_handles() {
|
||||||
size_t JNIHandleBlock::memory_usage() const {
|
size_t JNIHandleBlock::memory_usage() const {
|
||||||
return length() * sizeof(JNIHandleBlock);
|
return length() * sizeof(JNIHandleBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef PRODUCT
|
|
||||||
|
|
||||||
bool JNIHandles::is_local_handle(jobject handle) {
|
|
||||||
return JNIHandleBlock::any_contains(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool JNIHandleBlock::any_contains(jobject handle) {
|
|
||||||
assert(handle != NULL, "precondition");
|
|
||||||
for (JNIHandleBlock* current = _block_list; current != NULL; current = current->_block_list_link) {
|
|
||||||
if (current->contains(handle)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void JNIHandleBlock::print_statistics() {
|
|
||||||
int used_blocks = 0;
|
|
||||||
int free_blocks = 0;
|
|
||||||
int used_handles = 0;
|
|
||||||
int free_handles = 0;
|
|
||||||
JNIHandleBlock* block = _block_list;
|
|
||||||
while (block != NULL) {
|
|
||||||
if (block->_top > 0) {
|
|
||||||
used_blocks++;
|
|
||||||
} else {
|
|
||||||
free_blocks++;
|
|
||||||
}
|
|
||||||
used_handles += block->_top;
|
|
||||||
free_handles += (block_size_in_oops - block->_top);
|
|
||||||
block = block->_block_list_link;
|
|
||||||
}
|
|
||||||
tty->print_cr("JNIHandleBlocks statistics");
|
|
||||||
tty->print_cr("- blocks allocated: %d", used_blocks + free_blocks);
|
|
||||||
tty->print_cr("- blocks in use: %d", used_blocks);
|
|
||||||
tty->print_cr("- blocks free: %d", free_blocks);
|
|
||||||
tty->print_cr("- handles in use: %d", used_handles);
|
|
||||||
tty->print_cr("- handles free: %d", free_handles);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -84,7 +84,7 @@ class JNIHandles : AllStatic {
|
||||||
|
|
||||||
// Local handles
|
// Local handles
|
||||||
static jobject make_local(oop obj);
|
static jobject make_local(oop obj);
|
||||||
static jobject make_local(Thread* thread, oop obj, // Faster version when current thread is known
|
static jobject make_local(JavaThread* thread, oop obj, // Faster version when current thread is known
|
||||||
AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM);
|
AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM);
|
||||||
inline static void destroy_local(jobject handle);
|
inline static void destroy_local(jobject handle);
|
||||||
|
|
||||||
|
@ -104,20 +104,15 @@ class JNIHandles : AllStatic {
|
||||||
static void print();
|
static void print();
|
||||||
static void verify();
|
static void verify();
|
||||||
// The category predicates all require handle != NULL.
|
// The category predicates all require handle != NULL.
|
||||||
static bool is_local_handle(Thread* thread, jobject handle);
|
static bool is_local_handle(JavaThread* thread, jobject handle);
|
||||||
static bool is_frame_handle(JavaThread* thread, jobject handle);
|
static bool is_frame_handle(JavaThread* thread, jobject handle);
|
||||||
static bool is_global_handle(jobject handle);
|
static bool is_global_handle(jobject handle);
|
||||||
static bool is_weak_global_handle(jobject handle);
|
static bool is_weak_global_handle(jobject handle);
|
||||||
static size_t global_handle_memory_usage();
|
static size_t global_handle_memory_usage();
|
||||||
static size_t weak_global_handle_memory_usage();
|
static size_t weak_global_handle_memory_usage();
|
||||||
|
|
||||||
#ifndef PRODUCT
|
|
||||||
// Is handle from any local block of any thread?
|
|
||||||
static bool is_local_handle(jobject handle);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// precondition: handle != NULL.
|
// precondition: handle != NULL.
|
||||||
static jobjectRefType handle_type(Thread* thread, jobject handle);
|
static jobjectRefType handle_type(JavaThread* thread, jobject handle);
|
||||||
|
|
||||||
// Garbage collection support(global handles only, local handles are traversed from thread)
|
// Garbage collection support(global handles only, local handles are traversed from thread)
|
||||||
// Traversal of regular global handles
|
// Traversal of regular global handles
|
||||||
|
@ -145,6 +140,7 @@ class JNIHandleBlock : public CHeapObj<mtInternal> {
|
||||||
|
|
||||||
uintptr_t _handles[block_size_in_oops]; // The handles
|
uintptr_t _handles[block_size_in_oops]; // The handles
|
||||||
int _top; // Index of next unused handle
|
int _top; // Index of next unused handle
|
||||||
|
int _allocate_before_rebuild; // Number of blocks to allocate before rebuilding free list
|
||||||
JNIHandleBlock* _next; // Link to next block
|
JNIHandleBlock* _next; // Link to next block
|
||||||
|
|
||||||
// The following instance variables are only used by the first block in a chain.
|
// The following instance variables are only used by the first block in a chain.
|
||||||
|
@ -152,17 +148,9 @@ class JNIHandleBlock : public CHeapObj<mtInternal> {
|
||||||
JNIHandleBlock* _last; // Last block in use
|
JNIHandleBlock* _last; // Last block in use
|
||||||
JNIHandleBlock* _pop_frame_link; // Block to restore on PopLocalFrame call
|
JNIHandleBlock* _pop_frame_link; // Block to restore on PopLocalFrame call
|
||||||
uintptr_t* _free_list; // Handle free list
|
uintptr_t* _free_list; // Handle free list
|
||||||
int _allocate_before_rebuild; // Number of blocks to allocate before rebuilding free list
|
|
||||||
|
|
||||||
// Check JNI, "planned capacity" for current frame (or push/ensure)
|
// Check JNI, "planned capacity" for current frame (or push/ensure)
|
||||||
size_t _planned_capacity;
|
size_t _planned_capacity;
|
||||||
|
|
||||||
#ifndef PRODUCT
|
|
||||||
JNIHandleBlock* _block_list_link; // Link for list below
|
|
||||||
static JNIHandleBlock* _block_list; // List of all allocated blocks (for debugging only)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static JNIHandleBlock* _block_free_list; // Free list of currently unused blocks
|
|
||||||
static int _blocks_allocated; // For debugging/printing
|
static int _blocks_allocated; // For debugging/printing
|
||||||
|
|
||||||
// Fill block with bad_handle values
|
// Fill block with bad_handle values
|
||||||
|
@ -176,11 +164,11 @@ class JNIHandleBlock : public CHeapObj<mtInternal> {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Handle allocation
|
// Handle allocation
|
||||||
jobject allocate_handle(oop obj, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM);
|
jobject allocate_handle(JavaThread* caller, oop obj, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM);
|
||||||
|
|
||||||
// Block allocation and block free list management
|
// Block allocation and block free list management
|
||||||
static JNIHandleBlock* allocate_block(Thread* thread = NULL, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM);
|
static JNIHandleBlock* allocate_block(JavaThread* thread = NULL, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM);
|
||||||
static void release_block(JNIHandleBlock* block, Thread* thread = NULL);
|
static void release_block(JNIHandleBlock* block, JavaThread* thread = NULL);
|
||||||
|
|
||||||
// JNI PushLocalFrame/PopLocalFrame support
|
// JNI PushLocalFrame/PopLocalFrame support
|
||||||
JNIHandleBlock* pop_frame_link() const { return _pop_frame_link; }
|
JNIHandleBlock* pop_frame_link() const { return _pop_frame_link; }
|
||||||
|
@ -203,10 +191,6 @@ class JNIHandleBlock : public CHeapObj<mtInternal> {
|
||||||
bool contains(jobject handle) const; // Does this block contain handle
|
bool contains(jobject handle) const; // Does this block contain handle
|
||||||
size_t length() const; // Length of chain starting with this block
|
size_t length() const; // Length of chain starting with this block
|
||||||
size_t memory_usage() const;
|
size_t memory_usage() const;
|
||||||
#ifndef PRODUCT
|
|
||||||
static bool any_contains(jobject handle); // Does any block currently in use contain handle
|
|
||||||
static void print_statistics();
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SHARE_RUNTIME_JNIHANDLES_HPP
|
#endif // SHARE_RUNTIME_JNIHANDLES_HPP
|
||||||
|
|
|
@ -48,7 +48,6 @@ Mutex* Module_lock = NULL;
|
||||||
Mutex* CompiledIC_lock = NULL;
|
Mutex* CompiledIC_lock = NULL;
|
||||||
Mutex* InlineCacheBuffer_lock = NULL;
|
Mutex* InlineCacheBuffer_lock = NULL;
|
||||||
Mutex* VMStatistic_lock = NULL;
|
Mutex* VMStatistic_lock = NULL;
|
||||||
Mutex* JNIHandleBlockFreeList_lock = NULL;
|
|
||||||
Mutex* JmethodIdCreation_lock = NULL;
|
Mutex* JmethodIdCreation_lock = NULL;
|
||||||
Mutex* JfieldIdCreation_lock = NULL;
|
Mutex* JfieldIdCreation_lock = NULL;
|
||||||
Monitor* JNICritical_lock = NULL;
|
Monitor* JNICritical_lock = NULL;
|
||||||
|
@ -259,7 +258,6 @@ void mutex_init() {
|
||||||
|
|
||||||
def(SharedDictionary_lock , PaddedMutex , safepoint);
|
def(SharedDictionary_lock , PaddedMutex , safepoint);
|
||||||
def(VMStatistic_lock , PaddedMutex , safepoint);
|
def(VMStatistic_lock , PaddedMutex , safepoint);
|
||||||
def(JNIHandleBlockFreeList_lock , PaddedMutex , nosafepoint-1); // handles are used by VM thread
|
|
||||||
def(SignatureHandlerLibrary_lock , PaddedMutex , safepoint);
|
def(SignatureHandlerLibrary_lock , PaddedMutex , safepoint);
|
||||||
def(SymbolArena_lock , PaddedMutex , nosafepoint);
|
def(SymbolArena_lock , PaddedMutex , nosafepoint);
|
||||||
def(ExceptionCache_lock , PaddedMutex , safepoint);
|
def(ExceptionCache_lock , PaddedMutex , safepoint);
|
||||||
|
|
|
@ -40,7 +40,6 @@ extern Mutex* Module_lock; // a lock on module and package
|
||||||
extern Mutex* CompiledIC_lock; // a lock used to guard compiled IC patching and access
|
extern Mutex* CompiledIC_lock; // a lock used to guard compiled IC patching and access
|
||||||
extern Mutex* InlineCacheBuffer_lock; // a lock used to guard the InlineCacheBuffer
|
extern Mutex* InlineCacheBuffer_lock; // a lock used to guard the InlineCacheBuffer
|
||||||
extern Mutex* VMStatistic_lock; // a lock used to guard statistics count increment
|
extern Mutex* VMStatistic_lock; // a lock used to guard statistics count increment
|
||||||
extern Mutex* JNIHandleBlockFreeList_lock; // a lock on the JNI handle block free list
|
|
||||||
extern Mutex* JmethodIdCreation_lock; // a lock on creating JNI method identifiers
|
extern Mutex* JmethodIdCreation_lock; // a lock on creating JNI method identifiers
|
||||||
extern Mutex* JfieldIdCreation_lock; // a lock on creating JNI static field identifiers
|
extern Mutex* JfieldIdCreation_lock; // a lock on creating JNI static field identifiers
|
||||||
extern Monitor* JNICritical_lock; // a lock used while entering and exiting JNI critical regions, allows GC to sometimes get in
|
extern Monitor* JNICritical_lock; // a lock used while entering and exiting JNI critical regions, allows GC to sometimes get in
|
||||||
|
|
|
@ -234,7 +234,6 @@ int WatcherThread::sleep() const {
|
||||||
void WatcherThread::run() {
|
void WatcherThread::run() {
|
||||||
assert(this == watcher_thread(), "just checking");
|
assert(this == watcher_thread(), "just checking");
|
||||||
|
|
||||||
this->set_active_handles(JNIHandleBlock::allocate_block());
|
|
||||||
while (true) {
|
while (true) {
|
||||||
assert(watcher_thread() == Thread::current(), "thread consistency check");
|
assert(watcher_thread() == Thread::current(), "thread consistency check");
|
||||||
assert(watcher_thread() == this, "thread consistency check");
|
assert(watcher_thread() == this, "thread consistency check");
|
||||||
|
|
|
@ -1169,13 +1169,6 @@ void os::print_location(outputStream* st, intptr_t x, bool verbose) {
|
||||||
st->print_cr(INTPTR_FORMAT " is a weak global jni handle", p2i(addr));
|
st->print_cr(INTPTR_FORMAT " is a weak global jni handle", p2i(addr));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifndef PRODUCT
|
|
||||||
// we don't keep the block list in product mode
|
|
||||||
if (JNIHandles::is_local_handle((jobject) addr)) {
|
|
||||||
st->print_cr(INTPTR_FORMAT " is a local jni handle", p2i(addr));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if addr belongs to a Java thread.
|
// Check if addr belongs to a Java thread.
|
||||||
|
|
|
@ -220,8 +220,6 @@ Thread::Thread() {
|
||||||
DEBUG_ONLY(_current_resource_mark = NULL;)
|
DEBUG_ONLY(_current_resource_mark = NULL;)
|
||||||
set_handle_area(new (mtThread) HandleArea(NULL));
|
set_handle_area(new (mtThread) HandleArea(NULL));
|
||||||
set_metadata_handles(new (ResourceObj::C_HEAP, mtClass) GrowableArray<Metadata*>(30, mtClass));
|
set_metadata_handles(new (ResourceObj::C_HEAP, mtClass) GrowableArray<Metadata*>(30, mtClass));
|
||||||
set_active_handles(NULL);
|
|
||||||
set_free_handle_block(NULL);
|
|
||||||
set_last_handle_mark(NULL);
|
set_last_handle_mark(NULL);
|
||||||
DEBUG_ONLY(_missed_ic_stub_refill_verifier = NULL);
|
DEBUG_ONLY(_missed_ic_stub_refill_verifier = NULL);
|
||||||
|
|
||||||
|
@ -536,9 +534,6 @@ bool Thread::claim_par_threads_do(uintx claim_token) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Thread::oops_do_no_frames(OopClosure* f, CodeBlobClosure* cf) {
|
void Thread::oops_do_no_frames(OopClosure* f, CodeBlobClosure* cf) {
|
||||||
if (active_handles() != NULL) {
|
|
||||||
active_handles()->oops_do(f);
|
|
||||||
}
|
|
||||||
// Do oop for ThreadShadow
|
// Do oop for ThreadShadow
|
||||||
f->do_oop((oop*)&_pending_exception);
|
f->do_oop((oop*)&_pending_exception);
|
||||||
handle_area()->oops_do(f);
|
handle_area()->oops_do(f);
|
||||||
|
@ -1003,6 +998,8 @@ JavaThread::JavaThread() :
|
||||||
_current_pending_monitor(NULL),
|
_current_pending_monitor(NULL),
|
||||||
_current_pending_monitor_is_from_java(true),
|
_current_pending_monitor_is_from_java(true),
|
||||||
_current_waiting_monitor(NULL),
|
_current_waiting_monitor(NULL),
|
||||||
|
_active_handles(NULL),
|
||||||
|
_free_handle_block(NULL),
|
||||||
_Stalled(0),
|
_Stalled(0),
|
||||||
|
|
||||||
_monitor_chunks(nullptr),
|
_monitor_chunks(nullptr),
|
||||||
|
@ -1930,6 +1927,28 @@ void JavaThread::verify_frame_info() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Push on a new block of JNI handles.
|
||||||
|
void JavaThread::push_jni_handle_block() {
|
||||||
|
// Allocate a new block for JNI handles.
|
||||||
|
// Inlined code from jni_PushLocalFrame()
|
||||||
|
JNIHandleBlock* old_handles = active_handles();
|
||||||
|
JNIHandleBlock* new_handles = JNIHandleBlock::allocate_block(this);
|
||||||
|
assert(old_handles != NULL && new_handles != NULL, "should not be NULL");
|
||||||
|
new_handles->set_pop_frame_link(old_handles); // make sure java handles get gc'd.
|
||||||
|
set_active_handles(new_handles);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pop off the current block of JNI handles.
|
||||||
|
void JavaThread::pop_jni_handle_block() {
|
||||||
|
// Release our JNI handle block
|
||||||
|
JNIHandleBlock* old_handles = active_handles();
|
||||||
|
JNIHandleBlock* new_handles = old_handles->pop_frame_link();
|
||||||
|
assert(new_handles != nullptr, "should never set active handles to null");
|
||||||
|
set_active_handles(new_handles);
|
||||||
|
old_handles->set_pop_frame_link(NULL);
|
||||||
|
JNIHandleBlock::release_block(old_handles, this);
|
||||||
|
}
|
||||||
|
|
||||||
void JavaThread::oops_do_no_frames(OopClosure* f, CodeBlobClosure* cf) {
|
void JavaThread::oops_do_no_frames(OopClosure* f, CodeBlobClosure* cf) {
|
||||||
// Verify that the deferred card marks have been flushed.
|
// Verify that the deferred card marks have been flushed.
|
||||||
assert(deferred_card_mark().is_empty(), "Should be empty during GC");
|
assert(deferred_card_mark().is_empty(), "Should be empty during GC");
|
||||||
|
@ -1937,6 +1956,10 @@ void JavaThread::oops_do_no_frames(OopClosure* f, CodeBlobClosure* cf) {
|
||||||
// Traverse the GCHandles
|
// Traverse the GCHandles
|
||||||
Thread::oops_do_no_frames(f, cf);
|
Thread::oops_do_no_frames(f, cf);
|
||||||
|
|
||||||
|
if (active_handles() != NULL) {
|
||||||
|
active_handles()->oops_do(f);
|
||||||
|
}
|
||||||
|
|
||||||
DEBUG_ONLY(verify_frame_info();)
|
DEBUG_ONLY(verify_frame_info();)
|
||||||
|
|
||||||
if (has_last_Java_frame()) {
|
if (has_last_Java_frame()) {
|
||||||
|
@ -2830,7 +2853,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
|
||||||
{ TraceTime timer("Start VMThread", TRACETIME_LOG(Info, startuptime));
|
{ TraceTime timer("Start VMThread", TRACETIME_LOG(Info, startuptime));
|
||||||
|
|
||||||
VMThread::create();
|
VMThread::create();
|
||||||
Thread* vmthread = VMThread::vm_thread();
|
VMThread* vmthread = VMThread::vm_thread();
|
||||||
|
|
||||||
if (!os::create_thread(vmthread, os::vm_thread)) {
|
if (!os::create_thread(vmthread, os::vm_thread)) {
|
||||||
vm_exit_during_initialization("Cannot create VM thread. "
|
vm_exit_during_initialization("Cannot create VM thread. "
|
||||||
|
@ -2842,7 +2865,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
|
||||||
{
|
{
|
||||||
MonitorLocker ml(Notify_lock);
|
MonitorLocker ml(Notify_lock);
|
||||||
os::start_thread(vmthread);
|
os::start_thread(vmthread);
|
||||||
while (vmthread->active_handles() == NULL) {
|
while (!vmthread->is_running()) {
|
||||||
ml.wait();
|
ml.wait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -238,12 +238,6 @@ class Thread: public ThreadShadow {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Active_handles points to a block of handles
|
|
||||||
JNIHandleBlock* _active_handles;
|
|
||||||
|
|
||||||
// One-element thread local free list
|
|
||||||
JNIHandleBlock* _free_handle_block;
|
|
||||||
|
|
||||||
// Point to the last handle mark
|
// Point to the last handle mark
|
||||||
HandleMark* _last_handle_mark;
|
HandleMark* _last_handle_mark;
|
||||||
|
|
||||||
|
@ -416,12 +410,6 @@ class Thread: public ThreadShadow {
|
||||||
OSThread* osthread() const { return _osthread; }
|
OSThread* osthread() const { return _osthread; }
|
||||||
void set_osthread(OSThread* thread) { _osthread = thread; }
|
void set_osthread(OSThread* thread) { _osthread = thread; }
|
||||||
|
|
||||||
// JNI handle support
|
|
||||||
JNIHandleBlock* active_handles() const { return _active_handles; }
|
|
||||||
void set_active_handles(JNIHandleBlock* block) { _active_handles = block; }
|
|
||||||
JNIHandleBlock* free_handle_block() const { return _free_handle_block; }
|
|
||||||
void set_free_handle_block(JNIHandleBlock* block) { _free_handle_block = block; }
|
|
||||||
|
|
||||||
// Internal handle support
|
// Internal handle support
|
||||||
HandleArea* handle_area() const { return _handle_area; }
|
HandleArea* handle_area() const { return _handle_area; }
|
||||||
void set_handle_area(HandleArea* area) { _handle_area = area; }
|
void set_handle_area(HandleArea* area) { _handle_area = area; }
|
||||||
|
@ -607,7 +595,6 @@ protected:
|
||||||
// Code generation
|
// Code generation
|
||||||
static ByteSize exception_file_offset() { return byte_offset_of(Thread, _exception_file); }
|
static ByteSize exception_file_offset() { return byte_offset_of(Thread, _exception_file); }
|
||||||
static ByteSize exception_line_offset() { return byte_offset_of(Thread, _exception_line); }
|
static ByteSize exception_line_offset() { return byte_offset_of(Thread, _exception_line); }
|
||||||
static ByteSize active_handles_offset() { return byte_offset_of(Thread, _active_handles); }
|
|
||||||
|
|
||||||
static ByteSize stack_base_offset() { return byte_offset_of(Thread, _stack_base); }
|
static ByteSize stack_base_offset() { return byte_offset_of(Thread, _stack_base); }
|
||||||
static ByteSize stack_size_offset() { return byte_offset_of(Thread, _stack_size); }
|
static ByteSize stack_size_offset() { return byte_offset_of(Thread, _stack_size); }
|
||||||
|
@ -746,6 +733,13 @@ class JavaThread: public Thread {
|
||||||
ObjectMonitor* volatile _current_pending_monitor; // ObjectMonitor this thread is waiting to lock
|
ObjectMonitor* volatile _current_pending_monitor; // ObjectMonitor this thread is waiting to lock
|
||||||
bool _current_pending_monitor_is_from_java; // locking is from Java code
|
bool _current_pending_monitor_is_from_java; // locking is from Java code
|
||||||
ObjectMonitor* volatile _current_waiting_monitor; // ObjectMonitor on which this thread called Object.wait()
|
ObjectMonitor* volatile _current_waiting_monitor; // ObjectMonitor on which this thread called Object.wait()
|
||||||
|
|
||||||
|
// Active_handles points to a block of handles
|
||||||
|
JNIHandleBlock* _active_handles;
|
||||||
|
|
||||||
|
// One-element thread local free list
|
||||||
|
JNIHandleBlock* _free_handle_block;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
volatile intptr_t _Stalled;
|
volatile intptr_t _Stalled;
|
||||||
|
|
||||||
|
@ -773,6 +767,15 @@ class JavaThread: public Thread {
|
||||||
Atomic::store(&_current_waiting_monitor, monitor);
|
Atomic::store(&_current_waiting_monitor, monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// JNI handle support
|
||||||
|
JNIHandleBlock* active_handles() const { return _active_handles; }
|
||||||
|
void set_active_handles(JNIHandleBlock* block) { _active_handles = block; }
|
||||||
|
JNIHandleBlock* free_handle_block() const { return _free_handle_block; }
|
||||||
|
void set_free_handle_block(JNIHandleBlock* block) { _free_handle_block = block; }
|
||||||
|
|
||||||
|
void push_jni_handle_block();
|
||||||
|
void pop_jni_handle_block();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MonitorChunk* _monitor_chunks; // Contains the off stack monitors
|
MonitorChunk* _monitor_chunks; // Contains the off stack monitors
|
||||||
// allocated during deoptimization
|
// allocated during deoptimization
|
||||||
|
@ -1283,6 +1286,8 @@ class JavaThread: public Thread {
|
||||||
static ByteSize exception_handler_pc_offset() { return byte_offset_of(JavaThread, _exception_handler_pc); }
|
static ByteSize exception_handler_pc_offset() { return byte_offset_of(JavaThread, _exception_handler_pc); }
|
||||||
static ByteSize is_method_handle_return_offset() { return byte_offset_of(JavaThread, _is_method_handle_return); }
|
static ByteSize is_method_handle_return_offset() { return byte_offset_of(JavaThread, _is_method_handle_return); }
|
||||||
|
|
||||||
|
static ByteSize active_handles_offset() { return byte_offset_of(JavaThread, _active_handles); }
|
||||||
|
|
||||||
// StackOverflow offsets
|
// StackOverflow offsets
|
||||||
static ByteSize stack_overflow_limit_offset() {
|
static ByteSize stack_overflow_limit_offset() {
|
||||||
return byte_offset_of(JavaThread, _stack_overflow_state._stack_overflow_limit);
|
return byte_offset_of(JavaThread, _stack_overflow_state._stack_overflow_limit);
|
||||||
|
@ -1745,4 +1750,13 @@ class UnlockFlagSaver {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class JNIHandleMark : public StackObj {
|
||||||
|
JavaThread* _thread;
|
||||||
|
public:
|
||||||
|
JNIHandleMark(JavaThread* thread) : _thread(thread) {
|
||||||
|
thread->push_jni_handle_block();
|
||||||
|
}
|
||||||
|
~JNIHandleMark() { _thread->pop_jni_handle_block(); }
|
||||||
|
};
|
||||||
|
|
||||||
#endif // SHARE_RUNTIME_THREAD_HPP
|
#endif // SHARE_RUNTIME_THREAD_HPP
|
||||||
|
|
|
@ -704,7 +704,6 @@
|
||||||
nonstatic_field(ThreadShadow, _pending_exception, oop) \
|
nonstatic_field(ThreadShadow, _pending_exception, oop) \
|
||||||
nonstatic_field(ThreadShadow, _exception_file, const char*) \
|
nonstatic_field(ThreadShadow, _exception_file, const char*) \
|
||||||
nonstatic_field(ThreadShadow, _exception_line, int) \
|
nonstatic_field(ThreadShadow, _exception_line, int) \
|
||||||
nonstatic_field(Thread, _active_handles, JNIHandleBlock*) \
|
|
||||||
nonstatic_field(Thread, _tlab, ThreadLocalAllocBuffer) \
|
nonstatic_field(Thread, _tlab, ThreadLocalAllocBuffer) \
|
||||||
nonstatic_field(Thread, _allocated_bytes, jlong) \
|
nonstatic_field(Thread, _allocated_bytes, jlong) \
|
||||||
nonstatic_field(NamedThread, _name, char*) \
|
nonstatic_field(NamedThread, _name, char*) \
|
||||||
|
@ -728,6 +727,7 @@
|
||||||
nonstatic_field(JavaThread, _stack_size, size_t) \
|
nonstatic_field(JavaThread, _stack_size, size_t) \
|
||||||
nonstatic_field(JavaThread, _vframe_array_head, vframeArray*) \
|
nonstatic_field(JavaThread, _vframe_array_head, vframeArray*) \
|
||||||
nonstatic_field(JavaThread, _vframe_array_last, vframeArray*) \
|
nonstatic_field(JavaThread, _vframe_array_last, vframeArray*) \
|
||||||
|
nonstatic_field(JavaThread, _active_handles, JNIHandleBlock*) \
|
||||||
volatile_nonstatic_field(JavaThread, _terminated, JavaThread::TerminatedTypes) \
|
volatile_nonstatic_field(JavaThread, _terminated, JavaThread::TerminatedTypes) \
|
||||||
nonstatic_field(Thread, _resource_area, ResourceArea*) \
|
nonstatic_field(Thread, _resource_area, ResourceArea*) \
|
||||||
nonstatic_field(CompilerThread, _env, ciEnv*) \
|
nonstatic_field(CompilerThread, _env, ciEnv*) \
|
||||||
|
|
|
@ -139,7 +139,7 @@ void VMThread::create() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VMThread::VMThread() : NamedThread() {
|
VMThread::VMThread() : NamedThread(), _is_running(false) {
|
||||||
set_name("VM Thread");
|
set_name("VM Thread");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,10 +152,10 @@ static VM_None halt_op("Halt");
|
||||||
void VMThread::run() {
|
void VMThread::run() {
|
||||||
assert(this == vm_thread(), "check");
|
assert(this == vm_thread(), "check");
|
||||||
|
|
||||||
// Notify_lock wait checks on active_handles() to rewait in
|
// Notify_lock wait checks on is_running() to rewait in
|
||||||
// case of spurious wakeup, it should wait on the last
|
// case of spurious wakeup, it should wait on the last
|
||||||
// value set prior to the notify
|
// value set prior to the notify
|
||||||
this->set_active_handles(JNIHandleBlock::allocate_block());
|
Atomic::store(&_is_running, true);
|
||||||
|
|
||||||
{
|
{
|
||||||
MutexLocker ml(Notify_lock);
|
MutexLocker ml(Notify_lock);
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#ifndef SHARE_RUNTIME_VMTHREAD_HPP
|
#ifndef SHARE_RUNTIME_VMTHREAD_HPP
|
||||||
#define SHARE_RUNTIME_VMTHREAD_HPP
|
#define SHARE_RUNTIME_VMTHREAD_HPP
|
||||||
|
|
||||||
|
#include "runtime/atomic.hpp"
|
||||||
#include "runtime/perfDataTypes.hpp"
|
#include "runtime/perfDataTypes.hpp"
|
||||||
#include "runtime/nonJavaThread.hpp"
|
#include "runtime/nonJavaThread.hpp"
|
||||||
#include "runtime/thread.hpp"
|
#include "runtime/thread.hpp"
|
||||||
|
@ -59,6 +60,8 @@ public:
|
||||||
|
|
||||||
class VMThread: public NamedThread {
|
class VMThread: public NamedThread {
|
||||||
private:
|
private:
|
||||||
|
volatile bool _is_running;
|
||||||
|
|
||||||
static ThreadPriority _current_priority;
|
static ThreadPriority _current_priority;
|
||||||
|
|
||||||
static bool _should_terminate;
|
static bool _should_terminate;
|
||||||
|
@ -84,6 +87,7 @@ class VMThread: public NamedThread {
|
||||||
guarantee(false, "VMThread deletion must fix the race with VM termination");
|
guarantee(false, "VMThread deletion must fix the race with VM termination");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_running() const { return Atomic::load(&_is_running); }
|
||||||
|
|
||||||
// Tester
|
// Tester
|
||||||
bool is_VM_thread() const { return true; }
|
bool is_VM_thread() const { return true; }
|
||||||
|
|
|
@ -52,6 +52,7 @@ public class JavaThread extends Thread {
|
||||||
private static AddressField stackBaseField;
|
private static AddressField stackBaseField;
|
||||||
private static CIntegerField stackSizeField;
|
private static CIntegerField stackSizeField;
|
||||||
private static CIntegerField terminatedField;
|
private static CIntegerField terminatedField;
|
||||||
|
private static AddressField activeHandlesField;
|
||||||
|
|
||||||
private static JavaThreadPDAccess access;
|
private static JavaThreadPDAccess access;
|
||||||
|
|
||||||
|
@ -95,6 +96,7 @@ public class JavaThread extends Thread {
|
||||||
stackBaseField = type.getAddressField("_stack_base");
|
stackBaseField = type.getAddressField("_stack_base");
|
||||||
stackSizeField = type.getCIntegerField("_stack_size");
|
stackSizeField = type.getCIntegerField("_stack_size");
|
||||||
terminatedField = type.getCIntegerField("_terminated");
|
terminatedField = type.getCIntegerField("_terminated");
|
||||||
|
activeHandlesField = type.getAddressField("_active_handles");
|
||||||
|
|
||||||
UNINITIALIZED = db.lookupIntConstant("_thread_uninitialized").intValue();
|
UNINITIALIZED = db.lookupIntConstant("_thread_uninitialized").intValue();
|
||||||
NEW = db.lookupIntConstant("_thread_new").intValue();
|
NEW = db.lookupIntConstant("_thread_new").intValue();
|
||||||
|
@ -409,6 +411,14 @@ public class JavaThread extends Thread {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JNIHandleBlock activeHandles() {
|
||||||
|
Address a = activeHandlesField.getAddress(addr);
|
||||||
|
if (a == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new JNIHandleBlock(a);
|
||||||
|
}
|
||||||
|
|
||||||
public void printInfoOn(PrintStream tty) {
|
public void printInfoOn(PrintStream tty) {
|
||||||
|
|
||||||
tty.println("State: " + getThreadState().toString());
|
tty.println("State: " + getThreadState().toString());
|
||||||
|
|
|
@ -37,7 +37,6 @@ public class Thread extends VMObject {
|
||||||
// Thread::SuspendFlags enum constants
|
// Thread::SuspendFlags enum constants
|
||||||
private static int HAS_ASYNC_EXCEPTION;
|
private static int HAS_ASYNC_EXCEPTION;
|
||||||
|
|
||||||
private static AddressField activeHandlesField;
|
|
||||||
private static AddressField currentPendingMonitorField;
|
private static AddressField currentPendingMonitorField;
|
||||||
private static AddressField currentWaitingMonitorField;
|
private static AddressField currentWaitingMonitorField;
|
||||||
|
|
||||||
|
@ -59,7 +58,6 @@ public class Thread extends VMObject {
|
||||||
HAS_ASYNC_EXCEPTION = db.lookupIntConstant("JavaThread::_has_async_exception").intValue();
|
HAS_ASYNC_EXCEPTION = db.lookupIntConstant("JavaThread::_has_async_exception").intValue();
|
||||||
|
|
||||||
tlabFieldOffset = typeThread.getField("_tlab").getOffset();
|
tlabFieldOffset = typeThread.getField("_tlab").getOffset();
|
||||||
activeHandlesField = typeThread.getAddressField("_active_handles");
|
|
||||||
currentPendingMonitorField = typeJavaThread.getAddressField("_current_pending_monitor");
|
currentPendingMonitorField = typeJavaThread.getAddressField("_current_pending_monitor");
|
||||||
currentWaitingMonitorField = typeJavaThread.getAddressField("_current_waiting_monitor");
|
currentWaitingMonitorField = typeJavaThread.getAddressField("_current_waiting_monitor");
|
||||||
allocatedBytesField = typeThread.getJLongField("_allocated_bytes");
|
allocatedBytesField = typeThread.getJLongField("_allocated_bytes");
|
||||||
|
@ -81,14 +79,6 @@ public class Thread extends VMObject {
|
||||||
return new ThreadLocalAllocBuffer(addr.addOffsetTo(tlabFieldOffset));
|
return new ThreadLocalAllocBuffer(addr.addOffsetTo(tlabFieldOffset));
|
||||||
}
|
}
|
||||||
|
|
||||||
public JNIHandleBlock activeHandles() {
|
|
||||||
Address a = activeHandlesField.getAddress(addr);
|
|
||||||
if (a == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return new JNIHandleBlock(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
public long allocatedBytes() {
|
public long allocatedBytes() {
|
||||||
return allocatedBytesField.getValue(addr);
|
return allocatedBytesField.getValue(addr);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue