java是否缓存方法的结果

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.

我使用JMH来指定操作的复杂性。如果你从未与JMH合作过,别担心。JMH将多次启动
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