1,背景
调试代码的时候遇到continue处的breakpoint不起作用,故记录一下过程。
2,分析过程
2.1,复现
public class test {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
if (i == 5) {
System.out.println(i);
continue;
}
}
}
}
程序直接执行完并结束,断点未起作用
2.2,分析
check了一下代码的字节码
// class version 52.0 (52)
// access flags 0x21
public class test {
// compiled from: test.java
// access flags 0x1
public <init>()V
L0
LINENUMBER 8 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
RETURN
L1
LOCALVARIABLE this Lcom/test; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x9
public static main([Ljava/lang/String;)V
L0
LINENUMBER 11 L0
ICONST_0
ISTORE 1
L1
FRAME APPEND [I]
ILOAD 1
BIPUSH 10
IF_ICMPGE L2
L3
LINENUMBER 12 L3
ILOAD 1
ICONST_5
IF_ICMPNE L4
L5
LINENUMBER 13 L5
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
ILOAD 1
INVOKEVIRTUAL java/io/PrintStream.println (I)V
L4
LINENUMBER 11 L4
FRAME SAME
IINC 1 1
GOTO L1
L2
LINENUMBER 17 L2
FRAME CHOP 1
RETURN
L6
LOCALVARIABLE i I L1 L2 1
LOCALVARIABLE args [Ljava/lang/String; L0 L6 0
MAXSTACK = 2
MAXLOCALS = 2
}
通过字节码发现一个问题,并没有找到LINENUMBER 13,就好像这行代码并没写过一样。难道continue字段消失了?
将代码稍微调整一下:
public class test {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
if (i == 5) {
continue;
} else {
System.out.println(i);
}
}
}
}
可以发现断点生效了,然后check一下字节码:
// class version 52.0 (52)
// access flags 0x21
public class test {
// compiled from: test35.java
// access flags 0x1
public <init>()V
L0
LINENUMBER 8 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
RETURN
L1
LOCALVARIABLE this Ltest; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x9
public static main([Ljava/lang/String;)V
L0
LINENUMBER 11 L0
ICONST_0
ISTORE 1
L1
FRAME APPEND [I]
ILOAD 1
BIPUSH 10
IF_ICMPGE L2
L3
LINENUMBER 12 L3
ILOAD 1
ICONST_5
IF_ICMPNE L4
L5
LINENUMBER 13 L5
GOTO L6
L4
LINENUMBER 15 L4
FRAME SAME
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
ILOAD 1
INVOKEVIRTUAL java/io/PrintStream.println (I)V
L6
LINENUMBER 11 L6
FRAME SAME
IINC 1 1
GOTO L1
L2
LINENUMBER 18 L2
FRAME CHOP 1
RETURN
L7
LOCALVARIABLE i I L1 L2 1
LOCALVARIABLE args [Ljava/lang/String; L0 L7 0
MAXSTACK = 2
MAXLOCALS = 2
}
可以发现 出现了 LINENUMBER 13 L5
的内容了。
所以为什么会有这种差异呢?其实就是javac编译期对代码做了优化,示例中的代码的continue
逻辑是可以去掉的,然后javac编译时会做这个优化,因此断点调试时无法断点,并不是因为continue
具有特殊性。
3,结论
不得不佩服java编译器的强大,在断点gson代码的时候发现断点continue
一直未生效,还以为是找错地方了,原来是因为断点打在了可有可无的continue
上了。