idea在continue的breakpoint不起作用

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;
            }
        }
    }
}

image

程序直接执行完并结束,断点未起作用

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);
            }
        }
    }
}

image
可以发现断点生效了,然后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上了。

posted @ 2022-10-08 13:50  堕落门徒  阅读(272)  评论(0编辑  收藏  举报