Is this a bug? (unexpected IllegalMonitorStateException)

Tom Rodriguez Thomas.Rodriguez at Sun.COM
Thu Apr 24 11:00:54 PDT 2008


It's required that no locks are still held when the frame is exited.  By 
removing the exception handlers javac generated you are making it 
possible for the frame to return without unlocking the first lock. 
That's why the interpreter throws an illegal monitor state exception 
when you execute it with null.  The compiler won't compile it for the 
same reason.  We require that's a static analysis will tell us that 
monitor properly pair before we will compile something.  This means that 
you could write a complex piece of code which pairs properly dynamically 
but isn't statically provable and we wouldn't compile it but the 
interpreter would run it just fine.

tom

Stefan Ring wrote:
> Hi,
> 
> I'm working on CACAO at the moment and wanted to test how it behaves
> when an exception is thrown from a synchronized block for which no
> exception handlers have been created. So I built the following test
> program. Of course, I wanted to run it on hotspot first to find out how
> it should behave, assuming that hotspot is always right.
> 
> ==%< x.java
> class x {
>     public final static Object l = new Object();
>     private void test() {
>         Y y = new Y();
>         try {
>             y.dolocked(l, null);
>         } catch (Exception e) {
>             System.out.println("expecting NullPointerException");
>             e.printStackTrace();
>         }
>     }
>     public static void main(String[] args) {
>         new x().test();
>     }
> }
> ==%<==
> 
> and
> 
> ==%< Y.java
> class Y {
>     public void dolocked(Object o1, Object o2) {
>         synchronized (o1) {
>             synchronized (o2) {
>             }
>         }
>     }
> }
> ==%<==
> 
> When compiling class Y, the Java compiler will create implicit exception
> handlers, as javap -c will reveal. I then recreated the Y class file
> with jasmin, leaving out those exception handlers:
> 
> ==%< Y.j
> .class public Y
> .super java/lang/Object
> 
> .method public <init>()V
>         aload_0
>         invokenonvirtual java/lang/Object/<init>()V
>         return
> .end method
> 
> .method public dolocked(Ljava/lang/Object;Ljava/lang/Object;)V
>         .limit stack 3
>         .limit locals 5
>         aload_1
>         dup
>         astore_3
>         monitorenter
>         aload_2
>         dup
>         astore 4
>         monitorenter
>         aload 4
>         monitorexit
>         aload 3
>         monitorexit
>         return
> .end method
> ==%<==
> 
> The inner synchronized is supposed to fail because of the null
> reference. Much to my surprise, I get this, though:
> 
> expecting NullPointerException
> java.lang.IllegalMonitorStateException
>         at Y.dolocked(Y.j)
>         at x.test(x.java:6)
>         at x.main(x.java:13)
> 
>>From my understanding of things, normal program flow can never result in
> an IllegalMonitorStateException for this program. Delving a bit deeper
> into this, I found out that Y.dolocked will always be run by the
> interpreter in hotspot because the compiler says:
> 
> <method_not_compilable/>
> <failure reason='cannot parse method'/>
> 
> I know that the compiler will not compile methods without properly
> block-structured monitorenter and monitorexit instructions. This method
> is block-structured, though, but only in the absence of
> exceptions. Apparently, that's not good enough for the compiler.
> 
> The monitor on x.l is released, though.
> 
> 



More information about the hotspot-runtime-dev mailing list