理解JIT编译与优化
对Oracle JRockit JVM如何生成、编译、执行代码进行了介绍。
不仅仅是“黑匣子”
从用户的角度来看,JRockit JVM只是一个黑盒子,它将Java代码“转换”为高度优化的机器代码:将Java代码放入JVM的一端,而另一端则是特定平台的机器代码。
揭开黑匣子的盖子时,您会看到在针对特定操作系统优化代码之前采取的不同操作。在代码离开JVM之前,发生了以下的一些操作,数据结构更改和转换。
JVM如何编译代码
在Java应用程序的整个运行过程中,JRockit JVM中的代码生成器在后台运行,从而自动调整代码以使其发挥最佳性能。代码生成器分三个步骤工作,如图所示:
JVM运行JIT编译
代码生成的第一步是即是(JIT)编译,通过此编译,可以在未针对平台高度优化生成的代码的情况下启动和运行Java应用程序。尽管JIT实际上不是JVM标准的一部分,但它仍然是Java的基本组件。从理论上讲,只要调用Java方法,JIT就会使用,它将JIT的字节码编译为本地机器代码,从而“及时”编译以执行。
编译方法后,JRockit JVM直接调用该方法的已编译代码,而不用尝试对其进行解释,从而使应用程序的运行更快。但是,在运行开始期间,将执行数千个新方法,这会使JRockit JVM的实际启动速度比其他JVM慢。这是由于JIT运行和编译方法的大量开销。因此,如果您运行的是没有JIT的JVM,则该JVM可以快速启动,但运行速度通常较慢。如果运行包含JIT的JVM,则它可以启动缓慢,但是运行很快。在某个时候,您可能会发现启动JVM比运行应用程序花费的时间更长。
在启动时使用所有可用的优化来编译所有方法会对启动时间产生负面影响。因此,JIT编译不会在启动时完全优化所有方法。
JVM监视线程
在第二阶段,JRockit JVM使用一种复杂的,低成本的,基于采样的技术来确定哪些功能值得优化:“sampler thread”会定期唤醒,并检查几个应用程序线程的状态。它标识每个线程正在执行的内容,并记录一些执行历史记录。跟踪所有方法的信息,并且当感觉到方法正在大量使用时(换句话说,“hot”),该方法专用于优化。通常,在应用程序的早期运行阶段会出现大量此类优化机会,随着执行的继续,速度会降低。
JVM运行优化
在第三阶段,JVM对它认为是最常用的“hot”方法进行了方法的优化。此优化在后台运行,不会干扰正在运行的应用程序。
举例说明代码优化
此示例说明了JRockit JVM优化Java代码的一些方式。该示例相当简短,但可以使您大致了解如何优化实际的Java代码。
注意,这里没有讨论许多优化Java应用程序的方法。
在以下图示中,您可以查看优化前后的代码情况。差异可能看起来并不实质,但是请注意,每次运行A类时,优化的代码都不需要运行到B类。
优化过程
当Oracle JRockit JVM优化代码时,它会通过几个步骤来获得最佳的优化。上图显示了优化前后方法的外观。在下图中,您对JVM在Java应用程序代码本身级别上可能经历的几个优化步骤中可能发生的情况进行了解释。但是请注意,一些优化出现在汇编代码的级别。
参考资料
https://docs.oracle.com/cd/E13150_01/jrockit_jvm/jrockit/geninfo/diagnos/underst_jit.html