java - Sun 的 HotSpot JIT 编译器是否自动将 "final"应用于 Java 局部变量?

标签 java jit jvm-hotspot

我听说是这种情况,但我找不到权威的在线资源来证实这一点。

背景:一位同事喜欢将他的局部变量设为final。他这样做的原因之一是性能。我的观点是 Java 的 HotSpot Just In Time 编译器会自动检测不变的局部变量,并使它们成为final,因此我们自己这样做不会性能有任何好处。

请注意,我不是询问将局部变量设为 final 是否是良好的编码习惯,因为已经有很多(离题的)SO 问题了.

编辑:mrhobo 提出了关于优化整数文字字节码的一个很好的观点。我应该给出一个我正在谈论的代码类型的例子,以及我的问题:

Object doSomething(Foo foo) {
    if (foo == null) {
        return null;
    }

    final Bar bar = foo.getBar();
    final Baz baz = this.bazMap.get(bar);

    return new MyObject(bar, baz);
}

您是否认为在这种情况下会发生相同类型的优化,因为 barbaz 都标记为 final?还是 HotSpot 会自动检测到它们没有在方法范围内发生变化,并将它们视为 final

类似问题

最佳答案

要理解为什么编译器对局部变量的 final 完全不感兴趣,了解编译器工作原理的一些背景知识会有所帮助。基本上没有编译器对源代码(或字节码)本身进行操作,而是将其解析为某种中间表示形式(在应用优化时通常是几种不同的表示形式)。几乎我所知道的每个编译器都使用某种形式的静态单一赋值 或短 SSA 形式作为其中间表示。

顾名思义,SSA 形式基本上意味着每个变量只被赋值一次。为了更清楚地说明这一点,假设我们有以下简单的代码片段:

y = 4
x = 5
y = 6
z = x + y

在 SSA 形式中,这看起来像下面这样:

y_1 = 4
x_1 = 5
y_2 = 6
z_1 = y_2 + x_1

那么我们为什么要这样做呢?因为它使许多编译器优化变得更加容易(例如,可以消除对 y 的第一次写入是微不足道的,因为我们从未读取过它)。因此,如果您愿意,您可能会认为每个变量对于编译器来说都是最终变量。

PS:循环和分支确实让这个问题变得有点复杂,但我不想在那里过多地转移讨论 - 尽管 wiki 文章对如何解决这些问题有一个简短的解释。

关于java - Sun 的 HotSpot JIT 编译器是否自动将 "final"应用于 Java 局部变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22256013/

相关文章:

java - Struts 2/Foundation 5 - ModelDriven 类和文件上传

java - 合并多个图像使android非常慢

java - 为什么我没有打印却打印出这个

java - 如何将 JSON 中的各个数据片段提取为字符串?

java-8 - 如何使用uprobe追踪OpenJDK HotSpot源代码?

node.js - 为什么空对象比非空对象占用更多内存?

ios - 是否禁止在 AppStore 的 iOS 应用程序中使用 JIT(即时)编译代码?

android - 你将如何改进 Dalvik? Android的虚拟机

java - 当 java jvm 编译字节码时,该代码在进程空间中的什么位置?

memory-management - 无法使用 JStat 连接到远程 JVM