如何找出JVM应用于我的代码的优化?

JVM(尤其是HotSpot VM)因其在运行时可以应用的大量优化而闻名。

有没有办法查看某段代码,看看JVM实际上对它做了什么?

一个问题是“JVM实际上对它做了什么”在调用之间发生了变化,因为JVM可以自由地重新生成代码。

作为一个例子,我几天前调查了Hotspot与虚拟方法相比final方法的作用。 从微观基准来看,我的结论是:

  • 客户端JVM:如果该方法实际上是final (没有任何加载的类覆盖它),则JVM使用非虚拟调用。 之后,如果加载一个覆盖此方法的类,JVM将更改JIT代码以使调用成为虚拟。 因此宣布为final并没有重大意义。

  • 服务器JVM:这里的final似乎也没有相关性。 似乎发生的情况是,JVM为您第一次使用任何类生成非虚拟调用,而与所加载的类无关。 之后,如果你从另一个类的对象进行调用,JVM将使用与此类似的东西修补所有调用(我猜它也会调用调用,以便它可以更改快速路径和慢速路径,如果它没有得到这是第一次):

     if(object instanceof ClassOfNonVirtualCall){
        对ClassOfNonVirtualCall.method进行非虚拟调用
     } else {
        对object.method进行虚拟调用
     }

如果您真的对查看生成的代码感兴趣,可以使用OpenJDK中的DEBUG JVM:

http://dlc.sun.com.edgesuite.net/jdk7/binaries/index.html

http://wikis.sun.com/display/HotSpotInternals/PrintAssembly

这是高度JVM特定的,您很可能需要在您正在查看的特定JVM中进行一些严肃的调查。

您可以在此处查看可用的H​​otSpot VM选项http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html

以下是一个非常好的资源:

http://wikis.sun.com/display/HotSpotInternals/Home

特别有趣的是“LogCompilation工具”和“LogCompilation概述”链接(不能像我刚刚注册的那样发布直接链接)。

这是一个关于HotSpot优化的好页面。 通过查看编译器发出的字节码可以看到一些优化。 其他优化是动态的,仅在运行时存在。 例如,HotSpot可以进行堆栈替换 ,直接在运行时修改堆栈。