Looking at the Java Virtual Machine Specification and compiled code tells us how "synchronized" blocks are implemented in java. The following code:
public void testSync()
{
Object obj = getSomeObject();
synchronized (obj) { doSomething(); }
}
...is roughly equivalent to this pseudocode:
public void testSync()
{
Object obj = getSomeObject();
Object __temp = obj;
monitorenter __temp;
try { doSomething(); }
finally { monitorexit __temp; }
}
...with one exception.
For some reason, the exception table displays two finally handlers. For example:
Exception table:
from to target type
12 20 23 any
23 25 23 any
The first handler is where I expect it to be, but the second handler is actually for the finally block of the first handler, and if it catches an exception it executes the same handler. You could visualize this poorly in the following way:
try { doSomething(); }
finally { beginTry: try { monitorexit __temp; } finally { goto beginTry; } }
Does anybody know why this is? If it were just the finally block, the second entry in the table would not be there. Besides, I can't see any possible reason for wanting to execute the finally block again if it's already thrown an exception.
Thanks, Brandon
monitorexit
instruction throws an exception is documented in the JVM spec: 1) if __temp is null, in which casemonitorenter
will recursively throwNullPointerException
s; 2) if this thread is not currently the owner of the monitor, in which case recursively trying again and again to "exit" the monitor is not going to help at all; 3) if the monitor has no current owner, which has the same problem. Therefore, if it throws an exception once, it's going to throw it again, an infinite number of times. – Unloosesynchronized
block would be incorrect. – Cuomo