Hi Jc,
I found your example very difficult to follow. AFAICS you will
potentially encounter monitor related events that are unrelated to the
st.wait in your test code. And there are races in the test - as soon as
st.wait releases the monitor lock then SecondThread can run, complete
the sleep and print "Hello from A". I don't think it is specified
exactly when the MONIOR_WAIT event is sent with respect to the releasing
of the monitor lock.
David
On 19/09/2017 3:45 AM, JC Beyler wrote:
Hi all,
When looking at the documentation of
https://docs.oracle.com/javase/7/docs/platform/jvmti/jvmti.html#MonitorWaited
, I see the following description:
"Sent when a thread finishes waiting on an object."
However, there seems to be a slight issue when the MONITOR_WAIT event
handler throws an exception.
Consider the following code:
A) The monitor wait handler throws
static void JNICALL
monitor_wait(jvmtiEnv* jvmti, JNIEnv *env,
jthread thread, jobject object, jlong timeout) {
fprintf(stderr, "Waiting!\n");
jclass newExcCls = env->FindClass("java/lang/IllegalArgumentException");
// Unable to find the new exception class, give up.
if (newExcCls == 0) {
return;
}
env->ThrowNew(newExcCls, "Exception from monitor_wait");
}
B) The monitor waited handler does a printf:
static void JNICALL
monitor_waited(jvmtiEnv* jvmti, JNIEnv *env,
jthread thread, jobject object, jboolean timed_out) {
fprintf(stderr, "Waited!\n");
}
B) A second thread that will be asked to wait:
class SecondThread extends Thread {
public void run() {
try {
Thread.sleep(1);
} catch(Exception e) {
}
System.out.println("Hello from A");
}
}
C) The main thread with the wait:
class Main extends Thread {
public static void main(String[] args) {
SecondThread st = new SecondThread();
synchronized (st) {
st.start();
try {
st.wait();
} catch(InterruptedException e) {
System.out.println("Exception caught!");
}
}
System.out.println("Done");
}
}
D) If I do this, what happens is that I get:
Waiting!
Waited!
Exception in thread "main" java.lang.IllegalArgumentException: Exception
from monitor_wait
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at Main.main(Main.java:9)
Hello from A
- As we see, we get the print out from waiting, print out from waited
and then the exception in the waiting.
E) If instead, we do st.wait(-100) in the main method, we get:
Waiting!
Exception in thread "main" java.lang.IllegalArgumentException: Exception
from monitor_wait
at java.lang.Object.wait(Native Method)
at Main.main(Main.java:9)
Hello from A
Notes: the stack is slightly different, the printout waited is no longer
there however
F) If finally, we don't throw in the waiting handler but leave the
st.wait(-100) in place:
Waiting!
Exception in thread "main" java.lang.IllegalArgumentException: timeout
value is negative
at java.lang.Object.wait(Native Method)
at Main.main(Main.java:9)
Hello from A
The question thus becomes: is this normal that there is a slight
difference between D/E/F?
Should we try to fix it to have a single behavior in the three cases,
and if so, which would be the behavior that should be the default?
Let me know if you would like to see a full code to easily replicate, I
gave the big parts but left out the Agent_OnLoad method for example.
Thanks!
Jc