When does MONITOR_WAITED get thrown?
David Holmes
david.holmes at oracle.com
Mon Sep 18 22:04:31 UTC 2017
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
>
More information about the serviceability-dev
mailing list