静态最终字段 vs TrustFinalNonStaticFields
假设我有这个简单的方法:
static final Integer me = Integer.parseInt("2");
static int go() {
return me * 2;
}
对于javac,不是一个常量(根据JLS规则),但对于JIT来说很可能是。me
我试图用以下方法测试它:
public class StaticFinal {
public static void main(String[] args) {
int hash = 0;
for(int i=0;i<1000_000;++i){
hash = hash ^ go();
}
System.out.println(hash);
}
static final Integer me = Integer.parseInt("2");
static int go() {
return me * 2;
}
}
并运行它:
java -XX:+UnlockDiagnosticVMOptions
-XX:-TieredCompilation
"-XX:CompileCommand=print,StaticFinal.go"
-XX:PrintAssemblyOptions=intel
StaticFinal.java
我不知道组装很好,但这是显而易见的:
mov eax,0x4
的结果立即,即:JIT“可信”为常量,因此.go
4
me
2 * 2 = 4
如果我删除并将代码更改为:static
public class NonStaticFinal {
static NonStaticFinal instance = new NonStaticFinal();
public static void main(String[] args) {
int hash = 0;
for(int i=0;i<1000_000;++i){
hash = hash ^ instance.go();
}
System.out.println(hash);
}
final Integer me = Integer.parseInt("2");
int go() {
return me * 2;
}
}
并运行它:
java -XX:+UnlockDiagnosticVMOptions
-XX:-TieredCompilation
"-XX:CompileCommand=print,NonStaticFinal.go"
-XX:PrintAssemblyOptions=intel
NonStaticFinal.java
我确实在组装中看到:
shl eax,1
这实际上是 with 的乘法,通过移位完成。因此,JIT不相信它是一个常量,这是意料之中的。me
2
me
现在的问题是。我以为如果我添加标志,我会看到相同的,即:运行:TrustFinalNonStaticFields
mov eax 0x4
java -XX:+UnlockDiagnosticVMOptions
-XX:-TieredCompilation
"-XX:CompileCommand=print,NonStaticFinal.go"
-XX:+UnlockExperimentalVMOptions
-XX:+TrustFinalNonStaticFields
-XX:PrintAssemblyOptions=intel
NonStaticFinal.java
应该显示 ,但令我惊讶的是它没有,并且代码保持为:mov eax,0x4
shl eax,1
有人可以解释发生了什么以及我错过了什么吗?