【问题标题】:Can a java compiler optimize this code away?java编译器可以优化这段代码吗?
【发布时间】:2014-10-23 23:52:56
【问题描述】:

java 编译器或运行时(或任何其他语言编译器)是否足够聪明,可以实现分支 3 永远不会发生并对其进行优化?我已经在许多初级开发人员那里看到过这种“防御性编程”,我想知道这种负担是否会留在字节码中。

import java.util.Random;


class Example
{
    public static void main(String[] args) {
        int x = new Random().nextInt() % 10;
        if ( x < 5 )
        {
            System.out.println("Case 1");
        }
        else
            if ( x >= 5 )
            {
                System.out.println("Case 2");
            }
            else
            {
                System.out.println("Case 3");
            }

    }
}

甚至这个更直白的案例

boolean bool = new Random().nextBoolean();
if ( bool )
{
    System.out.println("Case 1");
}
else
    if ( bool )
    {
        System.out.println("Case 2");
    }

【问题讨论】:

  • JITC 可能会解决这个问题。或者至少会从分析中发现它非常罕见,因此以某种方式优化测试并将实际代码移出线。 (javac 将其优化掉是非常不寻常的。)
  • 旁白:请致电nextInt(n) 而不是nextInt() % n。它处理各种棘手的情况。 docs.oracle.com/javase/7/docs/api/java/util/…

标签: java optimization dead-code unreachable-code


【解决方案1】:

我拥有的 Java 8 编译器似乎没有对其进行优化。编译后使用“javap -c”查看字节码:

  public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class java/util/Random
       3: dup
       4: invokespecial #3                  // Method java/util/Random."<init>":()V
       7: invokevirtual #4                  // Method java/util/Random.nextInt:()I
      10: bipush        10
      12: irem
      13: istore_1
      14: iload_1
      15: iconst_5
      16: if_icmpge     30
      19: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
      22: ldc           #6                  // String Case 1
      24: invokevirtual #7                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      27: goto          54
      30: iload_1
      31: iconst_5
      32: if_icmplt     46
      35: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
      38: ldc           #8                  // String Case 2
      40: invokevirtual #7                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      43: goto          54
      46: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
      49: ldc           #9                  // String Case 3
      51: invokevirtual #7                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      54: return
}

字节码中仍然存在字符串“Case 3”。

【讨论】:

  • Javac 从不优化这些东西。这是一项 JIT 编译器工作。
  • @leventov JIT 不会删除死代码,它只是坐在那里。也就是说,除了坐在那里之外,它也没有做任何事情。删除它(如果可以检测到的话)没有显着的时间优化。
猜你喜欢
  • 1970-01-01
  • 2013-09-11
  • 1970-01-01
  • 1970-01-01
  • 2012-12-29
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
相关资源
最近更新 更多