java是否缓存方法的结果
我使用JMH来指定操作的复杂性。如果你从未与JMH合作过,别担心。JMH将多次启动java是否缓存方法的结果,java,caching,jvm,microbenchmark,jmh,Java,Caching,Jvm,Microbenchmark,Jmh,我使用JMH来指定操作的复杂性。如果你从未与JMH合作过,别担心。JMH将多次启动estimateOperation方法,然后获得平均时间 问题:[缩小]此程序每次都会计算Math.cbrt(Integer.MAX\u值)?或者它只计算一次,然后返回缓存结果 @GenerateMicroBenchmark public void estimateOperation() { calculate(); } public int calculate() { return Math.
estimateOperation
方法,然后获得平均时间
问题:[缩小]此程序每次都会计算Math.cbrt(Integer.MAX\u值)
?或者它只计算一次,然后返回缓存结果
@GenerateMicroBenchmark
public void estimateOperation() {
calculate();
}
public int calculate() {
return Math.cbrt(Integer.MAX_VALUE);
}
问题:[广泛]:JVM是否缓存过这些方法的结果?否
简单地说,Java不会缓存方法结果,因为方法每次都可以返回不同的值。是的,每次调用该代码时,它都会调用该代码
public int calculate() {
return Math.cbrt(Integer.MAX_VALUE);
}
public double calculate();
Code:
0: ldc2_w #3 // double 2.147483647E9d
3: invokestatic #5 // Method java/lang/Math.cbrt:(D)D
6: dreturn
要拥有缓存,只需将该神奇数字替换为
私有静态最终字段
private static final double NUMBER = Math.cbrt(Integer.MAX_VALUE);
方法返回值从不被缓存。但是,JIT编译器在运行时可能会消除不必要的调用,这是由于某些优化,如常量折叠、常量传播、死代码消除、循环不变提升、方法内联等
例如,如果将
Math.cbrt
替换为Math.sqrt
或Math.pow
,则JIT编译后将根本不会调用该方法,因为调用将被常量替换。(优化不适用于cbrt
,因为这是一种罕见的方法,它属于本机调用,而不是由JVM内部化)。回答一个狭义的问题:它取决于JVM实现和代码的解释方式
对广泛问题的回答:不,因为正如Anubian也指出的那样,方法可以在每次调用时返回不同的值。哪里有
calculate()
呢?字节码并不能解释任何东西。例如,将cbrt
替换为sqrt
,并且不会每次调用该方法。答案取决于被调用的方法和环境。JIT优化(++)可能会导致调用被取消并替换为常量。@apangin那么您可以发布您的答案吗?@V_B当然可以。添加了一个扩展的答案。我不太确定我是否遵循了您所说的JIT优化Math.sqrt()
还委托给本机调用(至少从我正在查看的代码中),我不明白为什么JIT编译器不能以与Math.sqrt()
相同的方式优化Math.cbrt()
——这两种情况下都应该使用相同的技术。@user3580294这些调用可能会优化,也可能不会优化取决于JVM。如果我们谈论HotSpot(OpenJDK和Oracle JDK中最流行的JVM),Math.sqrt
将得到优化,因为它是一个,即JIT编译器不会将其视为一个方法,而是将调用替换为在线计算代码Math.cbrt
虽然不是一个热点,但由于其稀有性和缺少相应的CPU指令,它并没有成为热点。调用并没有被常量替换。当我测试这个时,它每次都会调用它。@AnubianNoob你是怎么测试的?我支持OP的使用——它通常会给你真实的结果。我运行它并检查时间<代码>用于(int i=0;i