【问题标题】:Why is Java compiler not optimizing a trivial method? [duplicate]为什么 Java 编译器不优化一个简单的方法? [复制]
【发布时间】:2016-05-24 21:19:16
【问题描述】:

我有一个简单的类用于说明目的:

public class Test {

    public int test1() {
        int result = 100;
        result = 200;
        return result;
    }

    public int test2() {
        return 200;
    }
}

编译器生成的字节码(由javap -c Test.class检查)如下:

public int test1();
Code:
   0: bipush        100
   2: istore_1
   3: sipush        200
   6: istore_1
   7: iload_1
   8: ireturn

public int test2();
Code:
   0: sipush        200
   3: ireturn

为什么编译器没有将test1 方法优化为为test2 方法生成的相同字节码?我希望它至少可以避免 result 变量的冗余初始化,因为很容易得出结论:根本没有使用值 100

我在 Eclipse 编译器和 javac 中都观察到了这一点。

javac 版本:1.8.0_72,作为 JDK 的一部分与 Java 一起安装:

Java(TM) SE Runtime Environment (build 1.8.0_72-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.72-b15, mixed mode)

【问题讨论】:

  • Java 语言规范 不需要像这样的任何优化,因此将“编译器”说成只有一个是没有意义的。你应该指出你正在使用什么编译器。
  • 经典答案是在 JVM 中完成优化 (stackoverflow.com/questions/5981460/…)
  • @ruakh 好话;添加了编译器信息。
  • 但是权威的答案会很好,我会悬赏原始问题,我们会看看会发生什么。
  • @PeterLawrey 虽然没有明确写下来,但编译器必须对常量表达式进行优化,以使字节码在适合类文件格式的同时遵守 JLS。

标签: java javac bytecode compiler-optimization


【解决方案1】:

JVM 优化字节码,创建称为代码缓存 的东西。与 C++ 不同,JVM 可以收集有关您的程序的大量数据,例如,for 循环有多热?该代码块是否值得优化? 等等。所以在这里优化非常有用,并且通常会产生更好的结果。

如果您在从 java 转换为字节码时进行优化(即,当您调用 javac 时),您的代码可能最适合您的计算机,但不适用于某些不同的平台 .所以在这里优化是没有意义的。

作为示例,假设您的程序使用 AES 加密。现代 CPU 具有特定于 AES 的指令集,具有特殊的硬件,可以使加密速度更快。

如果 javac 尝试在编译时进行优化,那么它要么

  • 在软件级别优化指令,在这种情况下,您的编程将无法从现代 CPU 中受益,或者,
  • 将您的 AES 指令替换为等效的 CPU-AES 指令,仅在新 CPU 上支持,这会降低您的兼容性。

如果 javac 将它们保留在 byptcode 中,则运行在较新 CPU 上的 JVM 可以将它们识别为 AES 并利用此 CPU 功能,而运行在较旧 CPU 上的 JVM 可以优化它们运行时的软件级别(代码缓存),为您提供优化兼容性

【讨论】:

    【解决方案2】:

    典型的 Java 虚拟机在运行时优化您的程序,而不是在编译期间。在运行时,JVM 对您的应用程序有更多的了解,包括程序的实际行为和执行程序的实际硬件。

    字节码只是对您的程序应该如何运行的描述。运行时可以免费对您的字节码应用任何优化。

    当然,有人可能会争辩说,即使在编译期间也可以应用这种微不足道的优化,但总的来说,不将优化分布在几个步骤中是有意义的。任何优化都会有效地导致原始程序的信息丢失,这可能会使其他优化变得不可能。这就是说,并非所有“最佳优化”总是显而易见的。一种简单的方法是在编译期间简单地放弃(几乎)所有优化并在运行时应用它们。

    【讨论】:

    • 是的——至少行号的信息会丢失,所以stacktrace不会准确;并且调试会更难。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-19
    • 2015-05-13
    • 2011-03-24
    • 1970-01-01
    • 2012-02-27
    • 1970-01-01
    • 2016-11-09
    相关资源
    最近更新 更多