每个试图利用JMH框架创建一些有意义的测试的人都会看到JMH样本测试(http://hg.openjdk.java.net/code-tools/jmh/file/tip/jmh-samples/src/main/java/ org/openjdk/jmh/samples /).当我们经历它们时,我们坚持使用死代码(JMHSample_08_DeadCode.java).
摘抄:
private double x = Math.PI;
@Benchmark
public void baseline() {
// do nothing, this is a baseline
}
@Benchmark
public void measureWrong() {
// This is wrong: result is not used, and the entire computation is optimized out.
Math.log(x);
}
Run Code Online (Sandbox Code Playgroud)
measureWrong()的测量值与基线测试的测量值大致相同.因为从不使用Math.log()的返回值.因此HotSpot编译器将消除死代码.好的,理解但是编译器如何确定可以消除Math.log().
当我们仔细观察测试时,我们注意到Math.log()是一种本机方法.本机调用转到操作系统并执行相应的lib.对?这导致我们假设编译器可以消除本机调用,如果它们的返回值未被使用且它们不执行io操作.
我们想知道如果存在于操作系统某处并且处理来自java世界的本机调用的lib不提供返回值但是执行操作(例如,日志记录)会是什么.这些说明会完全消失吗?
为了证明我们的假设,我们使用简单的JMH测试和本机调用重建了场景.我们编译了三个c-native libs来执行:
正如我们在JMH测试中调用它们(类似于measureWrong()测试),它们都没有被消除,甚至没有消除执行io操作的那个.由于测试结果,我们的假设无法确认.本机调用无法优化,这意味着Math.log()和自定义本机调用没有相同的基础.它们不是原生的.也许我们在我们的原生lib代码中犯了一个错误,至少测试1的本地调用应该已被删除.如果这是真的,我们将与您分享我们的代码.
所以我们进一步搜索并找到了一个术语Intrinsics,其中java代码将被替换为对应于体系结构非常优化的代码.java.lang.Math.log()具有这样的内部实现.Natives和Intrinsics之间有什么关系吗?如果上述Natives和Intrinsics之间关系的假设有效,编译器会执行以下步骤来消除本机调用吗?