例如,在这种情况下
int x;
for (...) {
... some work, y and z not changed
x = y / z;
... some code using x
}
是否允许JVM(实际上是JIT编译器)在x = y / z
循环和“某些工作”之前计算for
一次(可能有副作用或抛出不同的异常),如果它无法证明z
非零,要在“正确”的时刻抛出ArithmeticException
吗?
关于强制转换(可能导致ClassCastException
)和取消装箱(可能导致NullPointerException
)的相同问题,仍然假设在某些情况下JVM / JIT编译器无法证明该对象具有适当的类或未装箱的值为非空。
UPD。 morgano说这个问题专门用于JVM实现。在这种情况下,我的问题是关于Hotspot JVM / JIT编译器的实现。
答案 0 :(得分:2)
是的,HotSpot JVM通常可以这样做。
C2 JIT编译器的一个关键特性是推测优化。这意味着JIT可以在假设不抛出运行时异常的情况下进行编译。在这种情况下,它可以轻松应用 Common Subexpression Elimination , Loop Invariant Hoisting 和其他相关优化。
如果在某个时刻推测假设失败,JIT会解除该方法并继续在解释模式下执行,以便在正确的位置抛出运行时异常。
顺便说一句,我已经检查过生成的程序集,HotSpot确实在您的示例中只计算了一次x = y / z
。