上篇文章咱们讲到了JIT中的LogCompilation,将编译的日志都收集起来,存到日志文件里面,而且详细的解释了LogCompilation日志文件中的内容定义。今天咱们再和小师妹一块儿学习LogCompilation的姊妹篇PrintCompilation,看看都有什么妙用吧。java
小师妹:F师兄,上次你给讲的LogCompilation实在是太复杂了,生成的日志文件又多,彻底看不了,我其实只是想知道有哪些方法被编译成了机器码,有没有什么更加简单的办法呢?git
真理的大海,让未发现的一切事物躺卧在个人眼前,任我去探寻- 牛顿(英国)
固然有的,那就给你介绍一下LogCompilation的妹妹PrintCompilation,为何是妹妹呢?由于PrintCompilation输出的日志要比LogCompilation少太多了。github
老规矩,上上咱们的JMH运行代码,文章中使用的代码连接都会在文末注明,这里使用图片的缘由只是为了方便读者阅读代码:多线程
这里和上次的LogCompilation不一样的是,咱们使用:-XX:+PrintCompilation参数。架构
其实咱们还能够添加更多的参数,例如:app
-Xbatch -XX:-TieredCompilation -XX:+PrintCompilation
先讲一下-Xbatch。 jvm
通常来讲JIT编译器使用的是和主线程彻底不一样的新的线程。这样作的好处就是JIT能够和主线程并行执行,编译器的运行基本上不会影响到主线程的的运行。学习
可是有阴就有阳,有利就有弊。多线程在提升的处理速度的同时,带给咱们的就是输出日志的混乱。由于是并行执行的,咱们主线程的日志中,穿插了JIT编译器的线程日志。优化
若是使用-Xbatch就能够强迫JIT编译器使用主线程。这样咱们的输出日志就是井井有理的。真棒。this
再讲一下TieredCompilation。
为了更好的提高编译效率,JVM在JDK7中引入了分层编译Tiered compilation的概念。
大概来讲分层编译能够分为三层:
第一层就是禁用C1和C2编译器,这个时候没有JIT进行。
第二层就是只开启C1编译器,由于C1编译器只会进行一些简单的JIT优化,因此这个能够应对常规状况。
第三层就是同时开启C1和C2编译器。
在JDK8中,分层编译是默认开启的。由于不一样的编译级别处理编译的时间是不同的,后面层级的编译器启动的要比前面层级的编译器要慢,可是优化的程度更高。
这样咱们其实会产生不少中间的优化代码,这里咱们只是想分析最终的优化代码,因此咱们须要中止分层编译的功能。
最后是今天的主角:PrintCompilation。
PrintCompilation将会输出被编译方法的统计信息,所以使用PrintCompilation能够很方便的看出哪些是热点代码。热点代码也就意味着存在着被优化的可能性。
小师妹:F师兄,我照着你的例子运行了一下,结果果真清爽了不少。但是我仍是看不懂。
没有一我的能全面把握真理。小师妹,咱们始终在未知的路上前行。不懂就问,不会就学。
咱们再截个图看一下生成的日志吧。
由于日志太长了,为了节约你们的流量,我只截取了开头的部分和结尾的部分。
你们能够看到开头部分基本上都是java自带的类的优化。只有最后才是咱们本身写的类。
第一列是方法开始编译的时间。
第二列是简单的index。
第三列是一系列的flag的组合,有下面几个flag:
b Blocking compiler (always set for client) * Generating a native wrapper % On stack replacement (where the compiled code is running) ! Method has exception handlers s Method declared as synchronized n Method declared as native made non entrant compilation was wrong/incomplete, no future callers will use this version made zombie code is not in use and ready for GC
若是咱们没有关闭分层编译的话,在方法名前面还会有数字,表示是使用的那个编译器。
分层编译详细的来讲能够分为5个级别。
0表示是使用解释器,不使用JIT编译。
1,2,3是使用C1编译器(client)。
4是使用C2编译器(server)。
如今让咱们来看一下最后一列。
最后一列包含了方法名和方法的长度。注意这里的长度指的是字节码的长度。
若是字节码被编译成为机器码,长度会增长不少倍。
本文介绍了JIT中PrintCompilation的使用,并再次复习了JIT中的分层编译架构。但愿你们可以喜欢。
本文的例子https://github.com/ddean2009/learn-java-base-9-to-20
本文做者:flydean程序那些事本文连接:http://www.flydean.com/jvm-jit-printcompilation/
本文来源:flydean的博客
欢迎关注个人公众号:程序那些事,更多精彩等着您!