Skip to content
Permalink
Browse files
8247248: JVM TI Monitor queries might create JNI locals in another th…
…read when using handshakes

Reviewed-by: dholmes, dcubed, sspitsyn, ysuenaga
  • Loading branch information
robehn committed Jun 11, 2020
1 parent c563c3d commit 6a2e3ca206c3103d122bb3033af33aea51cc08cb
Showing 3 changed files with 28 additions and 21 deletions.
@@ -1200,18 +1200,19 @@ JvmtiEnv::GetThreadInfo(jthread thread, jvmtiThreadInfo* info_ptr) {
jvmtiError
JvmtiEnv::GetOwnedMonitorInfo(JavaThread* java_thread, jint* owned_monitor_count_ptr, jobject** owned_monitors_ptr) {
jvmtiError err = JVMTI_ERROR_NONE;
JavaThread* calling_thread = JavaThread::current();

// growable array of jvmti monitors info on the C-heap
GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list =
new (ResourceObj::C_HEAP, mtInternal) GrowableArray<jvmtiMonitorStackDepthInfo*>(1, true);

// It is only safe to perform the direct operation on the current
// thread. All other usage needs to use a direct handshake for safety.
if (java_thread == JavaThread::current()) {
err = get_owned_monitors(java_thread, owned_monitors_list);
if (java_thread == calling_thread) {
err = get_owned_monitors(calling_thread, java_thread, owned_monitors_list);
} else {
// get owned monitors info with handshake
GetOwnedMonitorInfoClosure op(this, owned_monitors_list);
GetOwnedMonitorInfoClosure op(calling_thread, this, owned_monitors_list);
Handshake::execute_direct(&op, java_thread);
err = op.result();
}
@@ -1244,18 +1245,19 @@ JvmtiEnv::GetOwnedMonitorInfo(JavaThread* java_thread, jint* owned_monitor_count
jvmtiError
JvmtiEnv::GetOwnedMonitorStackDepthInfo(JavaThread* java_thread, jint* monitor_info_count_ptr, jvmtiMonitorStackDepthInfo** monitor_info_ptr) {
jvmtiError err = JVMTI_ERROR_NONE;
JavaThread* calling_thread = JavaThread::current();

// growable array of jvmti monitors info on the C-heap
GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list =
new (ResourceObj::C_HEAP, mtInternal) GrowableArray<jvmtiMonitorStackDepthInfo*>(1, true);

// It is only safe to perform the direct operation on the current
// thread. All other usage needs to use a direct handshake for safety.
if (java_thread == JavaThread::current()) {
err = get_owned_monitors(java_thread, owned_monitors_list);
if (java_thread == calling_thread) {
err = get_owned_monitors(calling_thread, java_thread, owned_monitors_list);
} else {
// get owned monitors info with handshake
GetOwnedMonitorInfoClosure op(this, owned_monitors_list);
GetOwnedMonitorInfoClosure op(calling_thread, this, owned_monitors_list);
Handshake::execute_direct(&op, java_thread);
err = op.result();
}
@@ -1291,14 +1293,15 @@ JvmtiEnv::GetOwnedMonitorStackDepthInfo(JavaThread* java_thread, jint* monitor_i
jvmtiError
JvmtiEnv::GetCurrentContendedMonitor(JavaThread* java_thread, jobject* monitor_ptr) {
jvmtiError err = JVMTI_ERROR_NONE;
JavaThread* calling_thread = JavaThread::current();

// It is only safe to perform the direct operation on the current
// thread. All other usage needs to use a direct handshake for safety.
if (java_thread == JavaThread::current()) {
err = get_current_contended_monitor(java_thread, monitor_ptr);
if (java_thread == calling_thread) {
err = get_current_contended_monitor(calling_thread, java_thread, monitor_ptr);
} else {
// get contended monitor information with handshake
GetCurrentContendedMonitorClosure op(this, monitor_ptr);
GetCurrentContendedMonitorClosure op(calling_thread, this, monitor_ptr);
Handshake::execute_direct(&op, java_thread);
err = op.result();
}
@@ -647,7 +647,7 @@ JvmtiEnvBase::count_locked_objects(JavaThread *java_thread, Handle hobj) {


jvmtiError
JvmtiEnvBase::get_current_contended_monitor(JavaThread *java_thread, jobject *monitor_ptr) {
JvmtiEnvBase::get_current_contended_monitor(JavaThread *calling_thread, JavaThread *java_thread, jobject *monitor_ptr) {
JavaThread *current_jt = JavaThread::current();
assert(current_jt == java_thread ||
current_jt == java_thread->active_handshaker(),
@@ -677,14 +677,14 @@ JvmtiEnvBase::get_current_contended_monitor(JavaThread *java_thread, jobject *mo
} else {
HandleMark hm;
Handle hobj(current_jt, obj);
*monitor_ptr = jni_reference(current_jt, hobj);
*monitor_ptr = jni_reference(calling_thread, hobj);
}
return JVMTI_ERROR_NONE;
}


jvmtiError
JvmtiEnvBase::get_owned_monitors(JavaThread* java_thread,
JvmtiEnvBase::get_owned_monitors(JavaThread *calling_thread, JavaThread* java_thread,
GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list) {
jvmtiError err = JVMTI_ERROR_NONE;
JavaThread *current_jt = JavaThread::current();
@@ -702,7 +702,7 @@ JvmtiEnvBase::get_owned_monitors(JavaThread* java_thread,
jvf = jvf->java_sender()) {
if (MaxJavaStackTraceDepth == 0 || depth++ < MaxJavaStackTraceDepth) { // check for stack too deep
// add locked objects for this frame into list
err = get_locked_objects_in_frame(current_jt, java_thread, jvf, owned_monitors_list, depth-1);
err = get_locked_objects_in_frame(calling_thread, java_thread, jvf, owned_monitors_list, depth-1);
if (err != JVMTI_ERROR_NONE) {
return err;
}
@@ -711,7 +711,7 @@ JvmtiEnvBase::get_owned_monitors(JavaThread* java_thread,
}

// Get off stack monitors. (e.g. acquired via jni MonitorEnter).
JvmtiMonitorClosure jmc(java_thread, current_jt, owned_monitors_list, this);
JvmtiMonitorClosure jmc(java_thread, calling_thread, owned_monitors_list, this);
ObjectSynchronizer::monitors_iterate(&jmc);
err = jmc.error();

@@ -1548,12 +1548,12 @@ VM_SetFramePop::doit() {

void
GetOwnedMonitorInfoClosure::do_thread(Thread *target) {
_result = ((JvmtiEnvBase *)_env)->get_owned_monitors((JavaThread *)target, _owned_monitors_list);
_result = ((JvmtiEnvBase *)_env)->get_owned_monitors(_calling_thread, (JavaThread *)target, _owned_monitors_list);
}

void
GetCurrentContendedMonitorClosure::do_thread(Thread *target) {
_result = ((JvmtiEnvBase *)_env)->get_current_contended_monitor((JavaThread *)target, _owned_monitor_ptr);
_result = ((JvmtiEnvBase *)_env)->get_current_contended_monitor(_calling_thread, (JavaThread *)target, _owned_monitor_ptr);
}

void
@@ -302,9 +302,9 @@ class JvmtiEnvBase : public CHeapObj<mtInternal> {
jvmtiError get_stack_trace(JavaThread *java_thread,
jint stack_depth, jint max_count,
jvmtiFrameInfo* frame_buffer, jint* count_ptr);
jvmtiError get_current_contended_monitor(JavaThread *java_thread,
jvmtiError get_current_contended_monitor(JavaThread *calling_thread, JavaThread *java_thread,
jobject *monitor_ptr);
jvmtiError get_owned_monitors(JavaThread* java_thread,
jvmtiError get_owned_monitors(JavaThread *calling_thread, JavaThread* java_thread,
GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list);
jvmtiError check_top_frame(JavaThread* current_thread, JavaThread* java_thread,
jvalue value, TosState tos, Handle* ret_ob_h);
@@ -376,19 +376,21 @@ class VM_SetFramePop : public VM_Operation {
// HandshakeClosure to get monitor information with stack depth.
class GetOwnedMonitorInfoClosure : public HandshakeClosure {
private:
JavaThread* _calling_thread;
JvmtiEnv *_env;
jvmtiError _result;
GrowableArray<jvmtiMonitorStackDepthInfo*> *_owned_monitors_list;

public:
GetOwnedMonitorInfoClosure(JvmtiEnv* env,
GetOwnedMonitorInfoClosure(JavaThread* calling_thread, JvmtiEnv* env,
GrowableArray<jvmtiMonitorStackDepthInfo*>* owned_monitor_list)
: HandshakeClosure("GetOwnedMonitorInfo"),
_calling_thread(calling_thread),
_env(env),
_result(JVMTI_ERROR_NONE),
_owned_monitors_list(owned_monitor_list) {}
void do_thread(Thread *target);
jvmtiError result() { return _result; }
void do_thread(Thread *target);
};


@@ -419,13 +421,15 @@ class VM_GetObjectMonitorUsage : public VM_Operation {
// HandshakeClosure to get current contended monitor.
class GetCurrentContendedMonitorClosure : public HandshakeClosure {
private:
JavaThread *_calling_thread;
JvmtiEnv *_env;
jobject *_owned_monitor_ptr;
jvmtiError _result;

public:
GetCurrentContendedMonitorClosure(JvmtiEnv *env, jobject *mon_ptr)
GetCurrentContendedMonitorClosure(JavaThread* calling_thread, JvmtiEnv *env, jobject *mon_ptr)
: HandshakeClosure("GetCurrentContendedMonitor"),
_calling_thread(calling_thread),
_env(env),
_owned_monitor_ptr(mon_ptr),
_result(JVMTI_ERROR_THREAD_NOT_ALIVE) {}

0 comments on commit 6a2e3ca

Please sign in to comment.