JRockit读书笔记I — Java代码的高效执行

《OracleJRockit:TheDefinitiveGuide》一书是由OracleJRockit的两位资深开发人员写的,其中的MarcusHirt更是JRockitMissionControl的leader,这本书详细的对OracleJRockit进行了介绍,最突出的特色很是系统化的介绍了一个JVM一般是如何实现的,而JRockit这样一个极为优秀的JVM又是作了哪些优化,为何作这些优化,这本书对于对JVM感兴趣的同窗而言应该是必读的一本书,其实即便对于JVM兴趣不强的同窗,里面的优化思路的介绍也是值得学习,本系列的blog主要是总结看这本书获得的一些收获,因为书中知识量巨大,所以得分红多篇blog来总结了。java

书的第二章为:AdaptiveCodeGeneration,在这章中做者向咱们讲解了一个优秀的JVM是如何来实现代码的高效执行的,感兴趣的同窗其实能够在不看下面blog内容以前,先考虑下若是是你作的话,你会怎么作来实现Java代码的高效执行呢,而后再对比下这章的内容,我想你能学到不少的,:)ide

用过Java的同窗都知道,Java是经过javac将Java源码编译为class文件,而后经过ClassLoader装载此class文件,以后就可执行此class了,要最高效的执行这个class,最好的方法莫过于class文件直接就是机器码,这样直接执行就能够了,但Java是跨平台的,所以class文件就不能是机器码了。性能

因为class文件不是直接的机器码,要执行它最简单的方法就是采用纯粹的解释方式,解释方式因为每次都得将class文件中的指令翻译为对应的机器环境的指令,效率是很低的。学习

为了能更高效的执行,同时又保持跨平台的特性,另一个方法就是在执行class时再将其翻译为对应的机器码,这个方法是比较靠谱的,所以不管是Hotspot、仍是JRockit,都采用了这种方式,也就是你们熟知的JIT(JustInTime)Compiler。优化

OK,既然以为在装载class后翻译成机器码去执行能够比较高效,那这个时候又会出现两种情况,是执行class的时候就马上翻译成机器码,仍是先用解释模式执行,而后到必定时机再翻译成机器码呢,之因此出现这两种情况,缘由在于将class翻译为机器码是须要消耗时间的,所以若是执行class的时候就马上翻译成机器码的话,也就会致使Java程序启动速度会比较慢,JRockit是这么认为的,JRockit的服务对象是server级应用,这类应用的特色是没那么在意启动速度,而更在意的是执行时的高效,并且若是执行的时候就马上翻译成机器码的话,就意味着压根不须要实现解释器,所以JRockit采起的方法是在执行class时直接编译为机器码,而Hotspot因为须要同时支持client和server应用,对于client应用而言,启动速度很是重要,所以Hotspot采用的是先解释执行,到了必定时机后再翻译成机器码。ui

若是认为就这样就完成了Java代码的执行的实现,那就过小看JVM了,因为JVM可以知道代码运行的所有情况,天然还能够作出更多更出色的提高代码执行速度的优化,例如标量替换、更好的inline等,后面再来细说,所以这样就出现了一个情况,何时对哪些代码来作这些更猛的优化呢。线程

真正值得作更猛的优化的代码天然是所谓的”热点”代码,如何来发现哪些代码是热点代码呢,一般有三种方法:
一、方法调用计数器
方法调用计数器是常见的方式,hotspot采用的即为这种,这种方式很差的地方就在于计数器自己常常是cpucachemisses的,所以稍微会有点影响性能。
二、对线程进行采样
可采用软件或硬件方式来实现,软件方式实现很差的地方在于采样的时候须要暂停线程,好处是由于是采样,不须要对全部方法进行计数,硬件方式天然是最好的,但不是全部的硬件都支持的,支持的硬件中最典型的是intelIA-64的CPU。翻译

在有了发现热点代码的方法后,接下来须要作的就是更猛的优化,有不少种,例如Java的代码中,一般会是接口方式的调用,但由于是接口方式的调用,因此其实默认状况下是很差作inline处理的,但JVM为了更高效的执行代码,如发现这代码为热点代码,那么就会作一些激进的优化,例如会假设这个接口只有一个实现,而后就能够直接将此实现对应的代码inline进来了(至于为何inline后效率更高,这个请参考编译原理之类的书),这些激进优化一样适合于if、抛异常这些情况,固然,当激进优化的条件失效时,就会逆优化回到以前基本编译的代码。
而其余的更猛的优化还包括根据线程执行路径进行逃逸分析等,后面再专门写一篇blog来说解下一些翻译为机器码的优化吧,其实大多都是编译原理的一些东西。code

书中在介绍JRockit如何实现本身的JITCompiler时,提到了Bytecode混淆以及bytecode优化,JRockit的态度是bytecode混淆时将name进行混淆是靠谱的,但若是对controlflow进行混淆,就不太好了,由于这有可能会致使jitcompile时的有些优化也作不了了,而bytecode优化,JRockit的态度是应该避免,由于没什么太大的意义,更主要的优化仍是得靠jitcompiler。server

JRockit的JITCompiler的实现和Hotspot另一个很大的不一样在于JRockit并未采用on-stackreplacement,据JRockit的研究,这个没有太大必要,固然,对于编写benchmark代码时则要注意这个不一样。

JITCompiler在compile时还须要考虑的几个重点问题:
一、为GC提供必要的信息;
二、为查错提供必要的信息,例如代码的行数、变量名等;

从这章的内容能够看到,JRockit为了可以让Java代码可以高效的执行,是作出了很是多的努力的,也能够看到不少JRockit与Hotspot不一样的地方,甚至能够看出Java代码的执行比C代码的执行高效都是有可能的,:)。

相关文章
相关标签/搜索