Community
Participate
Working Groups
When compiling the following (admittedly sick but valid) Java code within Eclipse and running it (using Oracle Java 1.7.0_60) I get a "java.lang.VerifyError: Expecting a stackmap frame at branch target 11". The code runs fine and prints 10 when first compiling it with javac. public class BreakContinue { public static void main(String[] args) { int i; for (i = 0; i < 10; i++) { try { break; } finally { continue; } } System.out.println(i); } } Exception in thread "main" java.lang.VerifyError: Expecting a stackmap frame at branch target 11 Exception Details: Location: Indecisive.decision()Z @11: if_icmplt Reason: Expected stackmap frame at this location. Bytecode: 0000000: 033b a700 0684 0001 1a10 0aa1 0000 b200 0000010: 101a b600 2204 ac Stackmap Table: append_frame(@5,Integer) same_frame(@8) at java.lang.Class.getDeclaredMethods0(Native Method) at java.lang.Class.privateGetDeclaredMethods(Class.java:2570) at java.lang.Class.getMethod0(Class.java:2813) at java.lang.Class.getMethod(Class.java:1663) at sun.launcher.LauncherHelper.getMainMethod(LauncherHelper.java:494) at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:486)
The stacktrace I posted belonged to an older version of my test program. Here's the correct one: Exception in thread "main" java.lang.VerifyError: Expecting a stackmap frame at branch target 11 Exception Details: Location: BreakContinue.main([Ljava/lang/String;)V @11: if_icmplt Reason: Expected stackmap frame at this location. Bytecode: 0000000: 033c a700 0684 0101 1b10 0aa1 0000 b200 0000010: 101b b600 16b1 Stackmap Table: append_frame(@5,Integer) same_frame(@8) at java.lang.Class.getDeclaredMethods0(Native Method) at java.lang.Class.privateGetDeclaredMethods(Class.java:2570) at java.lang.Class.getMethod0(Class.java:2813) at java.lang.Class.getMethod(Class.java:1663) at sun.launcher.LauncherHelper.getMainMethod(LauncherHelper.java:494) at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:486)
Reproduced with the last Mars build. Yet to figure out what went wrong.
This is a missing stack map frame. Might be related to wrong optimization in the bytecode. I'll take a look at it today.
Is that legal Java? While a break is pending we continue its loop (thus leaving the loop body) and then break from the loop from outside its body? Looks scary if you ask me :)
I think so: 14.1. Normal and Abrupt Completion of Statements: If all the steps are carried out as described, with no indication of abrupt completion, the statement is said to complete normally. However, certain events may prevent a statement from completing normally: •The break (§14.15), continue (§14.16), and return (§14.17) statements cause a transfer of control that may prevent normal completion of statements that contain them. 14.20.2. Execution of try-finally and try-catch-finally: A try statement with a finally block is executed by first executing the try block. Then there is a choice: • If execution of the try block completes abruptly for any other reason R, then the finally block is executed, and then there is a choice: ◦ If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and reason R is discarded). So it's like returning from inside a finally block but worse. Wonderful!
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet. If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant. -- The automated Eclipse Genie.
(In reply to Timo Kinnunen from comment #5) > I think so: > > 14.1. Normal and Abrupt Completion of Statements: > If all the steps are carried out as described, with no indication of abrupt > completion, the statement is said to complete normally. However, certain > events may prevent a statement from completing normally: > •The break (§14.15), continue (§14.16), and return (§14.17) statements cause > a transfer of control that may prevent normal completion of statements that > contain them. > > 14.20.2. Execution of try-finally and try-catch-finally: > A try statement with a finally block is executed by first executing the try > block. Then there is a choice: > • If execution of the try block completes abruptly for any other reason R, > then the finally block is executed, and then there is a choice: > ◦ If the finally block completes abruptly for reason S, then the try > statement completes abruptly for reason S (and reason R is discarded). To match this to the example: the reason "break" is discarded when we encounter "continue", right? So "finally { continue; }" is a straight-jacket to the try-block preventing it from terminating the loop by any means? "Interesting" ;p Using ecj HEAD I see: $ ecj -1.8 BreakContinue.java ---------- 1. WARNING in /tmp/BreakContinue.java (at line 7) } finally { continue; } ^^^^^^^^^^^^^^^^^^^^ finally block does not complete normally ---------- 1 problem (1 warning) $ java BreakContinue Error: Unable to initialize main class BreakContinue Caused by: java.lang.VerifyError: Instruction type does not match stack map Exception Details: Location: BreakContinue.main([Ljava/lang/String;)V @11: if_icmplt Reason: Current frame's stack size doesn't match stackmap. Current Frame: bci: @11 flags: { } locals: { '[Ljava/lang/String;', integer } stack: { integer, integer } Stackmap Frame: bci: @11 flags: { } locals: { '[Ljava/lang/String;', integer } stack: { } Bytecode: 0000000: 033c a700 0684 0101 1b10 0aa1 0000 b200 0000010: 0d1b b600 13b1 Stackmap Table: append_frame(@5,Integer) same_frame(@8) same_frame(@11) The byte code looks like this: public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: (0x0009) ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=2, args_size=1 0: iconst_0 1: istore_1 2: goto 8 5: iinc 1, 1 8: iload_1 9: bipush 10 11: if_icmplt 11 14: getstatic #13 // Field java/lang/System.out:Ljava/io/PrintStream; 17: iload_1 18: invokevirtual #19 // Method java/io/PrintStream.println:(I)V 21: return LineNumberTable: line 4: 0 line 4: 5 line 11: 14 line 12: 21 StackMapTable: number_of_entries = 3 frame_type = 252 /* append */ offset_delta = 5 locals = [ int ] frame_type = 2 /* same */ frame_type = 2 /* same */ Looks like the jump target is wrong in 11: if_icmplt 11 The difference in error messages is probably due to the recent rewrite of stack map generation. The new message can be observed since 4.14M1, but I don't believe it possible to generate a valid stack map for this code sequence.
Bulk move to 4.16
Bulk move of unassigned bugs to 4.17