8256314: JVM TI GetCurrentContendedMonitor is implemented incorrectly
Reviewed-by: dholmes, lmesnik
This commit is contained in:
parent
87b40c6ad2
commit
33aa4b26b1
@ -868,12 +868,7 @@ JvmtiEnv::GetThreadState(jthread thread, jint* thread_state_ptr) {
|
||||
// is a virtual thread.
|
||||
return err;
|
||||
}
|
||||
|
||||
if (java_lang_VirtualThread::is_instance(thread_oop)) {
|
||||
*thread_state_ptr = JvmtiEnvBase::get_vthread_state(thread_oop, java_thread);
|
||||
} else {
|
||||
*thread_state_ptr = JvmtiEnvBase::get_thread_state(thread_oop, java_thread);
|
||||
}
|
||||
*thread_state_ptr = JvmtiEnvBase::get_thread_or_vthread_state(thread_oop, java_thread);
|
||||
return JVMTI_ERROR_NONE;
|
||||
} /* end GetThreadState */
|
||||
|
||||
|
@ -813,6 +813,17 @@ JvmtiEnvBase::get_vthread_state(oop thread_oop, JavaThread* java_thread) {
|
||||
return state;
|
||||
}
|
||||
|
||||
jint
|
||||
JvmtiEnvBase::get_thread_or_vthread_state(oop thread_oop, JavaThread* java_thread) {
|
||||
jint state = 0;
|
||||
if (java_lang_VirtualThread::is_instance(thread_oop)) {
|
||||
state = JvmtiEnvBase::get_vthread_state(thread_oop, java_thread);
|
||||
} else {
|
||||
state = JvmtiEnvBase::get_thread_state(thread_oop, java_thread);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
jvmtiError
|
||||
JvmtiEnvBase::get_live_threads(JavaThread* current_thread, Handle group_hdl, jint *count_ptr, Handle **thread_objs_p) {
|
||||
jint count = 0;
|
||||
@ -933,11 +944,16 @@ JvmtiEnvBase::get_current_contended_monitor(JavaThread *calling_thread, JavaThre
|
||||
obj = mon->object();
|
||||
assert(obj != nullptr, "ObjectMonitor should have a valid object!");
|
||||
}
|
||||
// implied else: no contended ObjectMonitor
|
||||
} else {
|
||||
// thread is doing an Object.wait() call
|
||||
obj = mon->object();
|
||||
assert(obj != nullptr, "Object.wait() should have an object");
|
||||
oop thread_oop = get_vthread_or_thread_oop(java_thread);
|
||||
jint state = get_thread_or_vthread_state(thread_oop, java_thread);
|
||||
|
||||
if (state & JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER) {
|
||||
// thread is re-entering the monitor in an Object.wait() call
|
||||
obj = mon->object();
|
||||
assert(obj != nullptr, "Object.wait() should have an object");
|
||||
}
|
||||
}
|
||||
|
||||
if (obj == nullptr) {
|
||||
|
@ -388,9 +388,12 @@ class JvmtiEnvBase : public CHeapObj<mtInternal> {
|
||||
static jint get_thread_state_base(oop thread_oop, JavaThread* jt);
|
||||
static jint get_thread_state(oop thread_oop, JavaThread* jt);
|
||||
|
||||
// get virtual thread thread state
|
||||
// get virtual thread state
|
||||
static jint get_vthread_state(oop thread_oop, JavaThread* jt);
|
||||
|
||||
// get platform or virtual thread state
|
||||
static jint get_thread_or_vthread_state(oop thread_oop, JavaThread* jt);
|
||||
|
||||
// enumerates the live threads in the given thread group
|
||||
static jvmtiError get_live_threads(JavaThread* current_thread, Handle group_hdl, jint *count_ptr, Handle **thread_objs_p);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -1980,9 +1980,9 @@ JDWP "Java(tm) Debug Wire Protocol"
|
||||
)
|
||||
(Command CurrentContendedMonitor=9
|
||||
"Returns the object, if any, for which this thread is waiting. The "
|
||||
"thread may be waiting to enter a monitor, or it may be waiting, via "
|
||||
"the java.lang.Object.wait method, for another thread to invoke the "
|
||||
"notify method. "
|
||||
"thread may be waiting to enter the object's monitor, or in "
|
||||
"java.lang.Object.wait waiting to re-enter the monitor after being "
|
||||
"notified, interrupted, or timed-out."
|
||||
"The thread must be suspended, and the returned information is "
|
||||
"relevant only while the thread is suspended. "
|
||||
"Requires canGetCurrentContendedMonitor capability - see "
|
||||
|
@ -310,8 +310,8 @@ public interface ThreadReference extends ObjectReference {
|
||||
* for which this thread is currently waiting.
|
||||
* The thread can be waiting for a monitor through entry into a
|
||||
* synchronized method, the synchronized statement, or
|
||||
* {@link Object#wait}. The {@link #status} method can be used
|
||||
* to differentiate between the first two cases and the third.
|
||||
* {@link Object#wait} waiting to re-enter the monitor
|
||||
* after being notified, interrupted, or timed-out.
|
||||
* <p>
|
||||
* Not all target virtual machines support this operation.
|
||||
* Use {@link VirtualMachine#canGetCurrentContendedMonitor()}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -154,6 +154,7 @@ public class waitingthreads004 {
|
||||
fieldName = "lockingObject";
|
||||
display("CHECK2: checking waitingThreads method for ObjectReference of waitingthreads004a." + fieldName);
|
||||
objRef = (ObjectReference) debuggeeClass.getValue(debuggeeClass.fieldByName(fieldName));
|
||||
|
||||
try {
|
||||
List waitingThreads = objRef.waitingThreads();
|
||||
if (waitingThreads.size() != waitingthreads004a.threadCount) {
|
||||
@ -161,6 +162,12 @@ public class waitingthreads004 {
|
||||
complain("waitingThreads method returned list with unexpected size for " + fieldName +
|
||||
"\n\t expected value : " + waitingthreads004a.threadCount + "; got one : " + waitingThreads.size());
|
||||
} else {
|
||||
debuggee.VM().resume();
|
||||
debuggee.sendSignal(SIGNAL_GO);
|
||||
debuggee.receiveExpectedSignal(SIGNAL_GO);
|
||||
// tested thread must be blocked on re-entering monitor in lockingObject.wait()
|
||||
debuggee.VM().suspend();
|
||||
|
||||
// check waitingThreads list
|
||||
Iterator itr = waitingThreads.iterator();
|
||||
while (itr.hasNext()) {
|
||||
|
@ -32,11 +32,12 @@
|
||||
* The test checks an following assertion of
|
||||
* com.sun.jdi.ObjectReference.waitingThreads method spec:
|
||||
* Returns a List containing a ThreadReference for each thread currently
|
||||
* waiting for this object's monitor.
|
||||
* waiting to re-enter this object's monitor.
|
||||
* There are two test cases:
|
||||
* - An object with no waiting threads.
|
||||
* A list with zero size is expected to be returned by the method.
|
||||
* - An object with threads waiting in Object.wait(long) method.
|
||||
* - An object with threads waiting to re-enter the monitor after being
|
||||
* notified during execution of the Object.wait(long) method.
|
||||
* The debugger checks with expected results:
|
||||
* - a size of returned list of ThreadReferences,
|
||||
* - the names of thread references,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -96,13 +96,17 @@ public class waitingthreads004a {
|
||||
}
|
||||
|
||||
pipe.println(waitingthreads004.SIGNAL_GO);
|
||||
receiveSignal(waitingthreads004.SIGNAL_QUIT);
|
||||
receiveSignal(waitingthreads004.SIGNAL_GO);
|
||||
}
|
||||
display("exited: synchronized (waitnotifyObj) {}");
|
||||
|
||||
synchronized (lockingObject) {
|
||||
display("entered and notifyAll: synchronized (lockingObject) {}");
|
||||
lockingObject.notifyAll();
|
||||
|
||||
// tested thread must be blocked on re-entering monitor in lockingObject.wait()
|
||||
pipe.println(waitingthreads004.SIGNAL_GO);
|
||||
receiveSignal(waitingthreads004.SIGNAL_QUIT);
|
||||
}
|
||||
display("exited: synchronized (lockingObject) {}");
|
||||
|
||||
|
@ -46,7 +46,8 @@
|
||||
* Next, debugger obtains from debuggee classID for tested thread class
|
||||
* and threadID as the value of a class static field. Also debugger
|
||||
* suspends the thread before sending the tested command. The tested
|
||||
* thread is waiting for the object at this moment.
|
||||
* thread is waiting to re-enter the object monitor after being
|
||||
* notified during execution of the Object.wait(long) method.
|
||||
* Then, debugger creates command packet for ThreadReference.CurrenContendedMonitor
|
||||
* command with the found threadID as an argument, writes packet to
|
||||
* the transport channel, and waits for a reply packet.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -61,6 +61,7 @@ public class curcontmonitor001a {
|
||||
argumentHandler = new ArgumentHandler(args);
|
||||
log = new Log(out, argumentHandler);
|
||||
long timeout = argumentHandler.getWaitTime() * 60 * 1000; // milliseconds
|
||||
String signal = null;
|
||||
|
||||
// make communication pipe to debugger
|
||||
log.display("Creating pipe");
|
||||
@ -84,21 +85,19 @@ public class curcontmonitor001a {
|
||||
|
||||
// ensure that tested thread is waiting for monitor object
|
||||
synchronized (TestedClass.thread.monitor) {
|
||||
TestedClass.thread.monitor.notifyAll();
|
||||
|
||||
// send debugger signal READY
|
||||
log.display("Sending signal to debugger: " + curcontmonitor001.READY);
|
||||
pipe.println(curcontmonitor001.READY);
|
||||
|
||||
// wait for signal QUIT from debugeer
|
||||
log.display("Waiting for signal from debugger: " + curcontmonitor001.QUIT);
|
||||
signal = pipe.readln();
|
||||
log.display("Received signal from debugger: " + signal);
|
||||
}
|
||||
}
|
||||
|
||||
// wait for signal QUIT from debugeer
|
||||
log.display("Waiting for signal from debugger: " + curcontmonitor001.QUIT);
|
||||
String signal = pipe.readln();
|
||||
log.display("Received signal from debugger: " + signal);
|
||||
|
||||
// interrupt waiting thread
|
||||
log.display("Interrupting tested thread being waited");
|
||||
TestedClass.thread.interrupt();
|
||||
|
||||
// check received signal
|
||||
if (signal == null || !signal.equals(curcontmonitor001.QUIT)) {
|
||||
log.complain("Unexpected communication signal from debugee: " + signal
|
||||
|
Loading…
Reference in New Issue
Block a user