mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-19 18:44:38 +02:00
8242425: JVMTI monitor operations should use Thread-Local Handshakes
Reviewed-by: sspitsyn, dholmes
This commit is contained in:
parent
fc728278c2
commit
efcb6bd20e
4 changed files with 61 additions and 93 deletions
|
@ -1200,21 +1200,19 @@ JvmtiEnv::GetThreadInfo(jthread thread, jvmtiThreadInfo* info_ptr) {
|
||||||
jvmtiError
|
jvmtiError
|
||||||
JvmtiEnv::GetOwnedMonitorInfo(JavaThread* java_thread, jint* owned_monitor_count_ptr, jobject** owned_monitors_ptr) {
|
JvmtiEnv::GetOwnedMonitorInfo(JavaThread* java_thread, jint* owned_monitor_count_ptr, jobject** owned_monitors_ptr) {
|
||||||
jvmtiError err = JVMTI_ERROR_NONE;
|
jvmtiError err = JVMTI_ERROR_NONE;
|
||||||
JavaThread* calling_thread = JavaThread::current();
|
|
||||||
|
|
||||||
// growable array of jvmti monitors info on the C-heap
|
// growable array of jvmti monitors info on the C-heap
|
||||||
GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list =
|
GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list =
|
||||||
new (ResourceObj::C_HEAP, mtInternal) GrowableArray<jvmtiMonitorStackDepthInfo*>(1, true);
|
new (ResourceObj::C_HEAP, mtInternal) GrowableArray<jvmtiMonitorStackDepthInfo*>(1, true);
|
||||||
|
|
||||||
// It is only safe to perform the direct operation on the current
|
// It is only safe to perform the direct operation on the current
|
||||||
// thread. All other usage needs to use a vm-safepoint-op for safety.
|
// thread. All other usage needs to use a direct handshake for safety.
|
||||||
if (java_thread == calling_thread) {
|
if (java_thread == JavaThread::current()) {
|
||||||
err = get_owned_monitors(calling_thread, java_thread, owned_monitors_list);
|
err = get_owned_monitors(java_thread, owned_monitors_list);
|
||||||
} else {
|
} else {
|
||||||
// JVMTI get monitors info at safepoint. Do not require target thread to
|
// get owned monitors info with handshake
|
||||||
// be suspended.
|
GetOwnedMonitorInfoClosure op(this, owned_monitors_list);
|
||||||
VM_GetOwnedMonitorInfo op(this, calling_thread, java_thread, owned_monitors_list);
|
Handshake::execute_direct(&op, java_thread);
|
||||||
VMThread::execute(&op);
|
|
||||||
err = op.result();
|
err = op.result();
|
||||||
}
|
}
|
||||||
jint owned_monitor_count = owned_monitors_list->length();
|
jint owned_monitor_count = owned_monitors_list->length();
|
||||||
|
@ -1246,21 +1244,19 @@ JvmtiEnv::GetOwnedMonitorInfo(JavaThread* java_thread, jint* owned_monitor_count
|
||||||
jvmtiError
|
jvmtiError
|
||||||
JvmtiEnv::GetOwnedMonitorStackDepthInfo(JavaThread* java_thread, jint* monitor_info_count_ptr, jvmtiMonitorStackDepthInfo** monitor_info_ptr) {
|
JvmtiEnv::GetOwnedMonitorStackDepthInfo(JavaThread* java_thread, jint* monitor_info_count_ptr, jvmtiMonitorStackDepthInfo** monitor_info_ptr) {
|
||||||
jvmtiError err = JVMTI_ERROR_NONE;
|
jvmtiError err = JVMTI_ERROR_NONE;
|
||||||
JavaThread* calling_thread = JavaThread::current();
|
|
||||||
|
|
||||||
// growable array of jvmti monitors info on the C-heap
|
// growable array of jvmti monitors info on the C-heap
|
||||||
GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list =
|
GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list =
|
||||||
new (ResourceObj::C_HEAP, mtInternal) GrowableArray<jvmtiMonitorStackDepthInfo*>(1, true);
|
new (ResourceObj::C_HEAP, mtInternal) GrowableArray<jvmtiMonitorStackDepthInfo*>(1, true);
|
||||||
|
|
||||||
// It is only safe to perform the direct operation on the current
|
// It is only safe to perform the direct operation on the current
|
||||||
// thread. All other usage needs to use a vm-safepoint-op for safety.
|
// thread. All other usage needs to use a direct handshake for safety.
|
||||||
if (java_thread == calling_thread) {
|
if (java_thread == JavaThread::current()) {
|
||||||
err = get_owned_monitors(calling_thread, java_thread, owned_monitors_list);
|
err = get_owned_monitors(java_thread, owned_monitors_list);
|
||||||
} else {
|
} else {
|
||||||
// JVMTI get owned monitors info at safepoint. Do not require target thread to
|
// get owned monitors info with handshake
|
||||||
// be suspended.
|
GetOwnedMonitorInfoClosure op(this, owned_monitors_list);
|
||||||
VM_GetOwnedMonitorInfo op(this, calling_thread, java_thread, owned_monitors_list);
|
Handshake::execute_direct(&op, java_thread);
|
||||||
VMThread::execute(&op);
|
|
||||||
err = op.result();
|
err = op.result();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1295,16 +1291,15 @@ JvmtiEnv::GetOwnedMonitorStackDepthInfo(JavaThread* java_thread, jint* monitor_i
|
||||||
jvmtiError
|
jvmtiError
|
||||||
JvmtiEnv::GetCurrentContendedMonitor(JavaThread* java_thread, jobject* monitor_ptr) {
|
JvmtiEnv::GetCurrentContendedMonitor(JavaThread* java_thread, jobject* monitor_ptr) {
|
||||||
jvmtiError err = JVMTI_ERROR_NONE;
|
jvmtiError err = JVMTI_ERROR_NONE;
|
||||||
JavaThread* calling_thread = JavaThread::current();
|
|
||||||
|
|
||||||
// It is only safe to perform the direct operation on the current
|
// It is only safe to perform the direct operation on the current
|
||||||
// thread. All other usage needs to use a vm-safepoint-op for safety.
|
// thread. All other usage needs to use a direct handshake for safety.
|
||||||
if (java_thread == calling_thread) {
|
if (java_thread == JavaThread::current()) {
|
||||||
err = get_current_contended_monitor(calling_thread, java_thread, monitor_ptr);
|
err = get_current_contended_monitor(java_thread, monitor_ptr);
|
||||||
} else {
|
} else {
|
||||||
// get contended monitor information at safepoint.
|
// get contended monitor information with handshake
|
||||||
VM_GetCurrentContendedMonitor op(this, calling_thread, java_thread, monitor_ptr);
|
GetCurrentContendedMonitorClosure op(this, monitor_ptr);
|
||||||
VMThread::execute(&op);
|
Handshake::execute_direct(&op, java_thread);
|
||||||
err = op.result();
|
err = op.result();
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2020, 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
|
||||||
|
@ -647,13 +647,11 @@ JvmtiEnvBase::count_locked_objects(JavaThread *java_thread, Handle hobj) {
|
||||||
|
|
||||||
|
|
||||||
jvmtiError
|
jvmtiError
|
||||||
JvmtiEnvBase::get_current_contended_monitor(JavaThread *calling_thread, JavaThread *java_thread, jobject *monitor_ptr) {
|
JvmtiEnvBase::get_current_contended_monitor(JavaThread *java_thread, jobject *monitor_ptr) {
|
||||||
#ifdef ASSERT
|
JavaThread *current_jt = JavaThread::current();
|
||||||
uint32_t debug_bits = 0;
|
assert(current_jt == java_thread ||
|
||||||
#endif
|
current_jt == java_thread->active_handshaker(),
|
||||||
assert((SafepointSynchronize::is_at_safepoint() ||
|
"call by myself or at direct handshake");
|
||||||
java_thread->is_thread_fully_suspended(false, &debug_bits)),
|
|
||||||
"at safepoint or target thread is suspended");
|
|
||||||
oop obj = NULL;
|
oop obj = NULL;
|
||||||
ObjectMonitor *mon = java_thread->current_waiting_monitor();
|
ObjectMonitor *mon = java_thread->current_waiting_monitor();
|
||||||
if (mon == NULL) {
|
if (mon == NULL) {
|
||||||
|
@ -675,23 +673,21 @@ JvmtiEnvBase::get_current_contended_monitor(JavaThread *calling_thread, JavaThre
|
||||||
*monitor_ptr = NULL;
|
*monitor_ptr = NULL;
|
||||||
} else {
|
} else {
|
||||||
HandleMark hm;
|
HandleMark hm;
|
||||||
Handle hobj(Thread::current(), obj);
|
Handle hobj(current_jt, obj);
|
||||||
*monitor_ptr = jni_reference(calling_thread, hobj);
|
*monitor_ptr = jni_reference(current_jt, hobj);
|
||||||
}
|
}
|
||||||
return JVMTI_ERROR_NONE;
|
return JVMTI_ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
jvmtiError
|
jvmtiError
|
||||||
JvmtiEnvBase::get_owned_monitors(JavaThread *calling_thread, JavaThread* java_thread,
|
JvmtiEnvBase::get_owned_monitors(JavaThread* java_thread,
|
||||||
GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list) {
|
GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list) {
|
||||||
jvmtiError err = JVMTI_ERROR_NONE;
|
jvmtiError err = JVMTI_ERROR_NONE;
|
||||||
#ifdef ASSERT
|
JavaThread *current_jt = JavaThread::current();
|
||||||
uint32_t debug_bits = 0;
|
assert(current_jt == java_thread ||
|
||||||
#endif
|
current_jt == java_thread->active_handshaker(),
|
||||||
assert((SafepointSynchronize::is_at_safepoint() ||
|
"call by myself or at direct handshake");
|
||||||
java_thread->is_thread_fully_suspended(false, &debug_bits)),
|
|
||||||
"at safepoint or target thread is suspended");
|
|
||||||
|
|
||||||
if (java_thread->has_last_Java_frame()) {
|
if (java_thread->has_last_Java_frame()) {
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
|
@ -703,7 +699,7 @@ JvmtiEnvBase::get_owned_monitors(JavaThread *calling_thread, JavaThread* java_th
|
||||||
jvf = jvf->java_sender()) {
|
jvf = jvf->java_sender()) {
|
||||||
if (MaxJavaStackTraceDepth == 0 || depth++ < MaxJavaStackTraceDepth) { // check for stack too deep
|
if (MaxJavaStackTraceDepth == 0 || depth++ < MaxJavaStackTraceDepth) { // check for stack too deep
|
||||||
// add locked objects for this frame into list
|
// add locked objects for this frame into list
|
||||||
err = get_locked_objects_in_frame(calling_thread, java_thread, jvf, owned_monitors_list, depth-1);
|
err = get_locked_objects_in_frame(current_jt, java_thread, jvf, owned_monitors_list, depth-1);
|
||||||
if (err != JVMTI_ERROR_NONE) {
|
if (err != JVMTI_ERROR_NONE) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -712,7 +708,7 @@ JvmtiEnvBase::get_owned_monitors(JavaThread *calling_thread, JavaThread* java_th
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get off stack monitors. (e.g. acquired via jni MonitorEnter).
|
// Get off stack monitors. (e.g. acquired via jni MonitorEnter).
|
||||||
JvmtiMonitorClosure jmc(java_thread, calling_thread, owned_monitors_list, this);
|
JvmtiMonitorClosure jmc(java_thread, current_jt, owned_monitors_list, this);
|
||||||
ObjectSynchronizer::monitors_iterate(&jmc);
|
ObjectSynchronizer::monitors_iterate(&jmc);
|
||||||
err = jmc.error();
|
err = jmc.error();
|
||||||
|
|
||||||
|
@ -1542,24 +1538,13 @@ VM_SetFramePop::doit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
VM_GetOwnedMonitorInfo::doit() {
|
GetOwnedMonitorInfoClosure::do_thread(Thread *target) {
|
||||||
_result = JVMTI_ERROR_THREAD_NOT_ALIVE;
|
_result = ((JvmtiEnvBase *)_env)->get_owned_monitors((JavaThread *)target, _owned_monitors_list);
|
||||||
ThreadsListHandle tlh;
|
|
||||||
if (_java_thread != NULL && tlh.includes(_java_thread)
|
|
||||||
&& !_java_thread->is_exiting() && _java_thread->threadObj() != NULL) {
|
|
||||||
_result = ((JvmtiEnvBase *)_env)->get_owned_monitors(_calling_thread, _java_thread,
|
|
||||||
_owned_monitors_list);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
VM_GetCurrentContendedMonitor::doit() {
|
GetCurrentContendedMonitorClosure::do_thread(Thread *target) {
|
||||||
_result = JVMTI_ERROR_THREAD_NOT_ALIVE;
|
_result = ((JvmtiEnvBase *)_env)->get_current_contended_monitor((JavaThread *)target, _owned_monitor_ptr);
|
||||||
ThreadsListHandle tlh;
|
|
||||||
if (_java_thread != NULL && tlh.includes(_java_thread)
|
|
||||||
&& !_java_thread->is_exiting() && _java_thread->threadObj() != NULL) {
|
|
||||||
_result = ((JvmtiEnvBase *)_env)->get_current_contended_monitor(_calling_thread,_java_thread,_owned_monitor_ptr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2020, 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
|
||||||
|
@ -292,7 +292,8 @@ class JvmtiEnvBase : public CHeapObj<mtInternal> {
|
||||||
// get a field descriptor for the specified class and field
|
// get a field descriptor for the specified class and field
|
||||||
static bool get_field_descriptor(Klass* k, jfieldID field, fieldDescriptor* fd);
|
static bool get_field_descriptor(Klass* k, jfieldID field, fieldDescriptor* fd);
|
||||||
|
|
||||||
// JVMTI API helper functions which are called at safepoint or thread is suspended.
|
// JVMTI API helper functions which are called when target thread is suspended
|
||||||
|
// or at safepoint / thread local handshake.
|
||||||
jvmtiError get_frame_count(JvmtiThreadState *state, jint *count_ptr);
|
jvmtiError get_frame_count(JvmtiThreadState *state, jint *count_ptr);
|
||||||
jvmtiError get_frame_location(JavaThread* java_thread, jint depth,
|
jvmtiError get_frame_location(JavaThread* java_thread, jint depth,
|
||||||
jmethodID* method_ptr, jlocation* location_ptr);
|
jmethodID* method_ptr, jlocation* location_ptr);
|
||||||
|
@ -301,11 +302,10 @@ class JvmtiEnvBase : public CHeapObj<mtInternal> {
|
||||||
jvmtiError get_stack_trace(JavaThread *java_thread,
|
jvmtiError get_stack_trace(JavaThread *java_thread,
|
||||||
jint stack_depth, jint max_count,
|
jint stack_depth, jint max_count,
|
||||||
jvmtiFrameInfo* frame_buffer, jint* count_ptr);
|
jvmtiFrameInfo* frame_buffer, jint* count_ptr);
|
||||||
jvmtiError get_current_contended_monitor(JavaThread *calling_thread,
|
jvmtiError get_current_contended_monitor(JavaThread *java_thread,
|
||||||
JavaThread *java_thread,
|
jobject *monitor_ptr);
|
||||||
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);
|
||||||
GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list);
|
|
||||||
jvmtiError check_top_frame(JavaThread* current_thread, JavaThread* java_thread,
|
jvmtiError check_top_frame(JavaThread* current_thread, JavaThread* java_thread,
|
||||||
jvalue value, TosState tos, Handle* ret_ob_h);
|
jvalue value, TosState tos, Handle* ret_ob_h);
|
||||||
jvmtiError force_early_return(JavaThread* java_thread, jvalue value, TosState tos);
|
jvmtiError force_early_return(JavaThread* java_thread, jvalue value, TosState tos);
|
||||||
|
@ -376,27 +376,21 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// VM operation to get monitor information with stack depth.
|
// HandshakeClosure to get monitor information with stack depth.
|
||||||
class VM_GetOwnedMonitorInfo : public VM_Operation {
|
class GetOwnedMonitorInfoClosure : public HandshakeClosure {
|
||||||
private:
|
private:
|
||||||
JvmtiEnv *_env;
|
JvmtiEnv *_env;
|
||||||
JavaThread* _calling_thread;
|
|
||||||
JavaThread *_java_thread;
|
|
||||||
jvmtiError _result;
|
jvmtiError _result;
|
||||||
GrowableArray<jvmtiMonitorStackDepthInfo*> *_owned_monitors_list;
|
GrowableArray<jvmtiMonitorStackDepthInfo*> *_owned_monitors_list;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VM_GetOwnedMonitorInfo(JvmtiEnv* env, JavaThread* calling_thread,
|
GetOwnedMonitorInfoClosure(JvmtiEnv* env,
|
||||||
JavaThread* java_thread,
|
GrowableArray<jvmtiMonitorStackDepthInfo*>* owned_monitor_list)
|
||||||
GrowableArray<jvmtiMonitorStackDepthInfo*>* owned_monitor_list) {
|
: HandshakeClosure("GetOwnedMonitorInfo"),
|
||||||
_env = env;
|
_env(env),
|
||||||
_calling_thread = calling_thread;
|
_result(JVMTI_ERROR_NONE),
|
||||||
_java_thread = java_thread;
|
_owned_monitors_list(owned_monitor_list) {}
|
||||||
_owned_monitors_list = owned_monitor_list;
|
void do_thread(Thread *target);
|
||||||
_result = JVMTI_ERROR_NONE;
|
|
||||||
}
|
|
||||||
VMOp_Type type() const { return VMOp_GetOwnedMonitorInfo; }
|
|
||||||
void doit();
|
|
||||||
jvmtiError result() { return _result; }
|
jvmtiError result() { return _result; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -425,25 +419,21 @@ public:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// VM operation to get current contended monitor.
|
// HandshakeClosure to get current contended monitor.
|
||||||
class VM_GetCurrentContendedMonitor : public VM_Operation {
|
class GetCurrentContendedMonitorClosure : public HandshakeClosure {
|
||||||
private:
|
private:
|
||||||
JvmtiEnv *_env;
|
JvmtiEnv *_env;
|
||||||
JavaThread *_calling_thread;
|
|
||||||
JavaThread *_java_thread;
|
|
||||||
jobject *_owned_monitor_ptr;
|
jobject *_owned_monitor_ptr;
|
||||||
jvmtiError _result;
|
jvmtiError _result;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VM_GetCurrentContendedMonitor(JvmtiEnv *env, JavaThread *calling_thread, JavaThread *java_thread, jobject *mon_ptr) {
|
GetCurrentContendedMonitorClosure(JvmtiEnv *env, jobject *mon_ptr)
|
||||||
_env = env;
|
: HandshakeClosure("GetCurrentContendedMonitor"),
|
||||||
_calling_thread = calling_thread;
|
_env(env),
|
||||||
_java_thread = java_thread;
|
_owned_monitor_ptr(mon_ptr),
|
||||||
_owned_monitor_ptr = mon_ptr;
|
_result(JVMTI_ERROR_THREAD_NOT_ALIVE) {}
|
||||||
}
|
|
||||||
VMOp_Type type() const { return VMOp_GetCurrentContendedMonitor; }
|
|
||||||
jvmtiError result() { return _result; }
|
jvmtiError result() { return _result; }
|
||||||
void doit();
|
void do_thread(Thread *target);
|
||||||
};
|
};
|
||||||
|
|
||||||
// VM operation to get stack trace at safepoint.
|
// VM operation to get stack trace at safepoint.
|
||||||
|
|
|
@ -80,9 +80,7 @@
|
||||||
template(RedefineClasses) \
|
template(RedefineClasses) \
|
||||||
template(UpdateForPopTopFrame) \
|
template(UpdateForPopTopFrame) \
|
||||||
template(SetFramePop) \
|
template(SetFramePop) \
|
||||||
template(GetOwnedMonitorInfo) \
|
|
||||||
template(GetObjectMonitorUsage) \
|
template(GetObjectMonitorUsage) \
|
||||||
template(GetCurrentContendedMonitor) \
|
|
||||||
template(GetStackTrace) \
|
template(GetStackTrace) \
|
||||||
template(GetMultipleStackTraces) \
|
template(GetMultipleStackTraces) \
|
||||||
template(GetAllStackTraces) \
|
template(GetAllStackTraces) \
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue