JDK-4414101 : synchronized statement generates catch around the monitorexit
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 1.4.0,1.4.2_09,6
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: generic,solaris_7,solaris_8
  • CPU: generic,sparc
  • Submitted: 2001-02-10
  • Updated: 2002-02-20
  • Resolved: 2002-02-20
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Description
Code generation for try{}finally{} generates a catch block around the 
implicitly generated catch-all clause that jsrs to the finally
clause itself. This catch phrase names itself as the recipient!
This is useless.

More interestingly, the synchronized statement places a catch record 
around the monitorexit instruction so it can retry the instruction
if there is an asynchronous exception. Infortunately, that catch
record catches all, so an IllegalMonitorStateException will cause the VM
to enter an infinite loop retrying the monitorexit instruction forever.

frog$ cat -n Fbug.java
     1	class Fbug {
     2	    int m;
     3	
     4	    void test(Fbug f, int m) {
     5		try {
     6		    this.m = f.m;
     7		} finally {
     8		    this.m = 0;
     9		}
    10	    }
    11	}
frog$ javap -c Fbug
Compiled from Fbug.java
synchronized class Fbug extends java.lang.Object 
    /* ACC_SUPER bit set */
{
    int m;
    Fbug();
    void test(Fbug, int);
}

Method Fbug()
   0 aload_0
   1 invokespecial #1 <Method java.lang.Object()>
   4 return

Method void test(Fbug, int)
   0 aload_0
   1 aload_1
   2 getfield #2 <Field int m>
   5 putfield #2 <Field int m>
   8 jsr 20
  11 goto 29
  14 astore_3
  15 jsr 20
  18 aload_3
  19 athrow
  20 astore 4
  22 aload_0
  23 iconst_0
  24 putfield #2 <Field int m>
  27 ret 4
  29 return
Exception table:
   from   to  target type
     0    11    14   any
    14    18    14   any
frog$ 

Comments
PUBLIC COMMENTS ....
10-06-2004

EVALUATION While the code looks a bit silly for the try-finally, it is at least correct. The related code that we now generate for synchronized(){} statements illustrates the need for these strange catch blocks. It is necessary to handle asynchronous exceptions that can arise before the monitor is unlocked. Unfortunately, this catch block is too liberal in what it catches in the synchronized statement case. A IlegalMonitorStateException thrown from the monitorexit instruction will cause the VM to enter an infinite loop. The catch phrase should catch only ThreadDeath. As for the try-finally, we should avoid generating that extra exception record. neal.gafter@Eng 2001-02-13 The language spec requires the compiler to generate code that releases the monitor precisely once when exiting the synchronized block *for any reason*. See 14.18 sixth paragraph and section 17.13. Failure of the VM to release the lock is no excuse to ignore this part of the language spec: the compiler must not allow the synchronized block to be exited until the monitor is successfully unlocked. It is therefore correct for the compiler to generate code that fails to exit the monitored block when the monitor cannot be released. The inability of the VM to release the lock is a kind of deadlock that the Java programming language does not prevent or require detection of (17.13 last paragraph). Moreover, the possibility of an asynchronous throw of llegalMonitorStateException is yet another reason that such an exception should receive no special treatment. In short, javac's treatment of this in 1.4 is precisely correct. ###@###.### 2002-02-20
20-02-2002