为什么HotSpot会使用吊装优化以下内容?

use*_*414 20 java jvm-hotspot

在"Effective Java"中,作者提到了这一点

while (!done) i++;
Run Code Online (Sandbox Code Playgroud)

可以通过HotSpot进行优化

if (!done) {
    while (true) i++;
}
Run Code Online (Sandbox Code Playgroud)


我很困惑.变量done通常不是const,为什么编译器可以优化这种方式?

aha*_*tho 25

作者假设变量done是一个局部变量,它在Java内存模型中没有任何要求将其值暴露给没有同步原语的其他线程.或者换句话说:done除了此处显示的内容之外,任何代码都不会更改或查看其值.

在这种情况下,由于循环不会更改done其值,因此可以有效地忽略其值,并且编译器可以在循环外提升对该变量的求值,从而防止在循环的"热"部分中对其进行求值.这使循环运行得更快,因为它必须做更少的工作.

这也适用于更复杂的表达式,例如数组的长度:

int[] array = new int[10000];
for (int i = 0; i < array.length; ++i) {
    array[i] = Random.nextInt();
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,naive实现将评估数组的长度10,000次,但由于永远不会分配变量数组并且数组的长度永远不会改变,因此评估可以更改为:

int[] array = new int[10000];
for (int i = 0, $l = array.length; i < $l; ++i) {
    array[i] = Random.nextInt();
}
Run Code Online (Sandbox Code Playgroud)

此处的其他优化也适用于与吊装无关.

希望有所帮助.

  • 即使`done`是实例或类变量,只要它不是volatile,也可能发生这种优化. (5认同)
  • 我相信EJ的作者的观点是,因为JIT编译器*可以*这样优化,程序员不应该依赖于从不同线程改变的'done'的值.JIT编译器可能会优化此构造的代码,然后循环真的永远不会终止. (3认同)