How do I exit a monitor in bytecode properly?
Asked Answered
E

2

6

I was reading the JVM specification to try to figure out how to properly handle monitors. The example they give in the relevant section looks like this:

0   aload_1             // Push f
1   dup                 // Duplicate it on the stack
2   astore_2            // Store duplicate in local variable 2
3   monitorenter        // Enter the monitor associated with f
4   aload_0             // Holding the monitor, pass this and...
5   invokevirtual #5    // ...call Example.doSomething()V
8   aload_2             // Push local variable 2 (f)
9   monitorexit         // Exit the monitor associated with f
10  goto 18             // Complete the method normally
13  astore_3            // In case of any throw, end up here
14  aload_2             // Push local variable 2 (f)
15  monitorexit         // Be sure to exit the monitor!
16  aload_3             // Push thrown value...
17  athrow              // ...and rethrow value to the invoker
18  return              // Return in the normal case
Exception table:
From    To      Target      Type
4       10      13          any
13      16      13          any

I can not figure out why the second exception table entry is needed. If an exception is thrown by monitorexit do I really want to attempt to exit the monitor again? Possible exceptions thrown as far as I can tell are NullPointerException and IllegalMonitorStateException.

Erogenous answered 15/8, 2013 at 9:30 Comment(1)
Interesting! There's a Java bug about it, closed as "not an issue": bugs.sun.com/bugdatabase/view_bug.do?bug_id=4414101Petrochemical
L
4

There is an Java Bug for this that has been closed as "Not an issue" - https://bugs.java.com/bugdatabase/view_bug?bug_id=4414101. (Kudos to Tom Anderson for finding it.)

The Evaluation section of the Bug is really enlightening.

It starts by talking about dealing with "asynchronous" exceptions; i.e. the ThreadDeath exception that is how the (deprecated!) Thread.stop() method is implemented. The mysterious handler ensures that the monitor lock is released even if the "thread stop" happens at the critical point where the JVM is trying to release the lock.

Then Neil Gafter adds that even the hypothetical infinite loop (as described in this Question) is correct behaviour according to the JLS. The JLS says that monitor will always be released before the thread continues. If it is impossible to do that, then putting the thread into an infinite loop is more correct than doing anything else.

Lightner answered 15/8, 2013 at 13:43 Comment(0)
F
0

To be clear

block 0 :  0 -  3
block 1 :  4 - 10
block 2 : 13 - 16/17
block 3 : 18 

I agree that it it confusing to have a try/catch on the second block because this appears to be a possible infinite loop. i.e. if an exception occurs between 13 and 16 it jumps to 13 to handle it. I can only assume either

  • there is a safe, retry-able exception which it is try to protect itself from.
  • it is retained for an obscure backward compatibility reason.
  • there is no good reason for this and it is an artefact of how the byte code is generated.

I suspect it doesn't do anything useful, and I imagine someone at Oracle has had the same suspicious but didn't know for sure it could be removed. ;)

Fenske answered 15/8, 2013 at 9:41 Comment(5)
I don't understand this explanation. The second exception table entry covers the lines 13 to 16 ... doesn't it?Lightner
indeed it is a possible infinite loop. I edited class file and changed monitorenter with pop instruction, to cause IllegalMonitorStateException on monitorexit, and the program got cycling. Now the question is, what behaviour do we want? We can file a bug against java compiler.Footworn
I would file a bug, just in case they do something about it. ;)Fenske
Yea, well it is also possible that there is a sound reason for the mysterious extra exception table entry to be there ... and we're not smart enough to see it.Lightner
And in fact there is ... see my Answer. (I don't claim that I was smart enough to see it though :-) )Lightner

© 2022 - 2024 — McMap. All rights reserved.