From a comment below:
https://bugs.openjdk.java.net/browse/JDK-8208664?focusedCommentId=14202472&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-14202472
public class Cont {
public static void main(String[] args) {
foo(true, false);
}
static void foo(boolean a, boolean b) {
int i;
for (i = 0; i < 10; i++) {
if (a || b) {
continue; // breakpoint here does not work
}
System.out.println(i);
}
System.out.println(i);
}
}
Breakpoint at "continue" statement (line 10) does not trigger. javap shows the following bytecodes.
0: iconst_0
1: istore_2
2: iload_2
3: bipush 10
5: if_icmpge 32
8: iload_0
9: ifne 26
12: iload_1
13: ifeq 19
16: goto 26
19: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
22: iload_2
23: invokevirtual #4 // Method java/io/PrintStream.println:(I)V
26: iinc 2, 1
29: goto 2
32: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
35: iload_2
36: invokevirtual #4 // Method java/io/PrintStream.println:(I)V
39: return
LineNumberTable:
line 8: 0
line 9: 8
line 10: 16
line 12: 19
line 8: 26
line 14: 32
line 15: 39
The LineNumberTable says the "continue" at line 10 maps to the goto bytecode at line 16. However, the bytecodes at lines 8-9 are loading and checking 'a', and doing the goto (ifeq) for the continue at bytecode 9. So essentially the continue at line 10 logically maps to two separate goto's, one at bytecode offset 9 (ifeq) and one at bytecode offset 16, and the LineNumberTable only has the one at bytecode offset 16.
Adding a println before the continue causes different bytecode logic to be generated that doesn't have this problem:
5: if_icmpge 40
8: iload_0
9: ifne 16
12: iload_1
13: ifeq 27
16: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
19: ldc #4 // String about to continue...
21: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
24: goto 34
line 11: 24
I don't think this should be considered a jvmti or debugger bug. The issue lies in how javac is generating bytecodes, including the LineNumberTable. In order for this to work with the bytecode as generated, the LineNumberTable would need two entries for line #10, one at bytecode 9 and one at 16.
https://bugs.openjdk.java.net/browse/JDK-8208664?focusedCommentId=14202472&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-14202472
public class Cont {
public static void main(String[] args) {
foo(true, false);
}
static void foo(boolean a, boolean b) {
int i;
for (i = 0; i < 10; i++) {
if (a || b) {
continue; // breakpoint here does not work
}
System.out.println(i);
}
System.out.println(i);
}
}
Breakpoint at "continue" statement (line 10) does not trigger. javap shows the following bytecodes.
0: iconst_0
1: istore_2
2: iload_2
3: bipush 10
5: if_icmpge 32
8: iload_0
9: ifne 26
12: iload_1
13: ifeq 19
16: goto 26
19: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
22: iload_2
23: invokevirtual #4 // Method java/io/PrintStream.println:(I)V
26: iinc 2, 1
29: goto 2
32: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
35: iload_2
36: invokevirtual #4 // Method java/io/PrintStream.println:(I)V
39: return
LineNumberTable:
line 8: 0
line 9: 8
line 10: 16
line 12: 19
line 8: 26
line 14: 32
line 15: 39
The LineNumberTable says the "continue" at line 10 maps to the goto bytecode at line 16. However, the bytecodes at lines 8-9 are loading and checking 'a', and doing the goto (ifeq) for the continue at bytecode 9. So essentially the continue at line 10 logically maps to two separate goto's, one at bytecode offset 9 (ifeq) and one at bytecode offset 16, and the LineNumberTable only has the one at bytecode offset 16.
Adding a println before the continue causes different bytecode logic to be generated that doesn't have this problem:
5: if_icmpge 40
8: iload_0
9: ifne 16
12: iload_1
13: ifeq 27
16: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
19: ldc #4 // String about to continue...
21: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
24: goto 34
line 11: 24
I don't think this should be considered a jvmti or debugger bug. The issue lies in how javac is generating bytecodes, including the LineNumberTable. In order for this to work with the bytecode as generated, the LineNumberTable would need two entries for line #10, one at bytecode 9 and one at 16.