简介

上篇文章我们讲到了JIT中的LogCompilation,将编译的日志都收集起来,存到日志文件里面,并且详细的解释了LogCompilation日志文件中的内容定义。今天我们再和小师妹一起学习LogCompilation的姊妹篇PrintCompilation,看看都有什么妙用吧。

PrintCompilation

小师妹:F师兄,上次你给讲的LogCompilation实在是太复杂了,生成的日志文件又多,完全看不了,我其实只是想知道有哪些方法被编译成了机器码,有没有什么更加简单的办法呢?

真理的大海,让未发现的一切事物躺卧在我的眼前,任我去探寻- 牛顿(英国)

当然有的,那就给你介绍一下LogCompilation的妹妹PrintCompilation,为什么是妹妹呢?因为PrintCompilation输出的日志要比LogCompilation少太多了。

老规矩,上上我们的JMH运行代码,文章中使用的代码链接都会在文末注明,这里使用图片的原因只是为了方便读者阅读代码:

这里和上次的LogCompilation不同的是,我们使用:-XX:+PrintCompilation参数。

其实我们还可以添加更多的参数,例如:

-Xbatch -XX:-TieredCompilation -XX:+PrintCompilation

先讲一下-Xbatch。

一般来说JIT编译器使用的是和主线程完全不同的新的线程。这样做的好处就是JIT可以和主线程并行执行,编译器的运行基本上不会影响到主线程的的运行。

但是有阴就有阳,有利就有弊。多线程在提高的处理速度的同时,带给我们的就是输出日志的混乱。因为是并行执行的,我们主线程的日志中,穿插了JIT编译器的线程日志。

如果使用-Xbatch就可以强迫JIT编译器使用主线程。这样我们的输出日志就是井然有序的。真棒。

再讲一下TieredCompilation。

为了更好的提升编译效率,JVM在JDK7中引入了分层编译Tiered compilation的概念。

大概来说分层编译可以分为三层:

第一层就是禁用C1和C2编译器,这个时候没有JIT进行。

第二层就是只开启C1编译器,因为C1编译器只会进行一些简单的JIT优化,所以这个可以应对常规情况。

第三层就是同时开启C1和C2编译器。

在JDK8中,分层编译是默认开启的。因为不同的编译级别处理编译的时间是不一样的,后面层级的编译器启动的要比前面层级的编译器要慢,但是优化的程度更高。

这样我们其实会产生很多中间的优化代码,这里我们只是想分析最终的优化代码,所以我们需要停止分层编译的功能。

最后是今天的主角:PrintCompilation。

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的博客

欢迎关注我的公众号:程序那些事,更多精彩等着您!

小师妹学JVM之:JIT中的PrintCompilation的更多相关文章

  1. 小师妹学JVM之:JIT中的PrintAssembly

    目录 简介 使用PrintAssembly 输出过滤 总结 简介 想不想了解JVM最最底层的运行机制?想不想从本质上理解java代码的执行过程?想不想对你的代码进行进一步的优化和性能提升? 如果你的回 ...

  2. 小师妹学JVM之:JIT中的LogCompilation

    目录 简介 LogCompilation简介 LogCompilation的使用 解析LogCompilation文件 总结 简介 我们知道在JVM中为了加快编译速度,引入了JIT即时编译的功能.那么 ...

  3. 小师妹学JVM之:JIT中的PrintAssembly续集

    目录 简介 JDK8和JDK14中的PrintAssembly JDK8中使用Assembly JDK14中的Assembly 在JMH中使用Assembly 总结 简介 上篇文章和小师妹一起介绍了P ...

  4. 小师妹学JVM之:JDK14中JVM的性能优化

    目录 简介 String压缩 分层编译(Tiered Compilation) Code Cache分层 新的JIT编译器Graal 前置编译 压缩对象指针 Zero-Based 压缩指针 Escap ...

  5. 小师妹学JVM之:深入理解JIT和编译优化-你看不懂系列

    目录 简介 JIT编译器 Tiered Compilation分层编译 OSR(On-Stack Replacement) Deoptimization 常见的编译优化举例 Inlining内联 Br ...

  6. 小师妹学JVM之:JVM中的Safepoints

    目录 简介 GC的垃圾回收器 分代回收器中的问题 safepoints safepoint一般用在什么地方 总结 简介 java程序员都听说过GC,大家也都知道GC的目的是扫描堆空间,然后将那些标记为 ...

  7. 小师妹学JVM之:cache line对代码性能的影响

    目录 简介 一个奇怪的现象 两个问题的答案 CPU cache line inc 和 add 总结 简介 读万卷书不如行万里路,讲了这么多assembly和JVM的原理与优化,今天我们来点不一样的实战 ...

  8. 小师妹学JVM之:JVM的架构和执行过程

    目录 简介 JVM是一种标准 java程序的执行顺序 JVM的架构 类加载系统 运行时数据区域 执行引擎 总结 简介 JVM也叫Java Virtual Machine,它是java程序运行的基础,负 ...

  9. 小师妹学JavaIO之:NIO中那些奇怪的Buffer

    目录 简介 Buffer的分类 Big Endian 和 Little Endian aligned内存对齐 总结 简介 妖魔鬼怪快快显形,今天F师兄帮助小师妹来斩妖除魔啦,什么BufferB,Buf ...

随机推荐

  1. PowerShell读写文件,行的去重

    Power Shell类似bash终端能够直接操作文件,使用其内置的Get-Content函数,配合一定的参数,能方便地读取文件和重定向. 1. Power Shell>>Get-Cont ...

  2. 50个SQL语句(MySQL版) 问题五

    --------------------------表结构-------------------------- student(StuId,StuName,StuAge,StuSex) 学生表 tea ...

  3. centos7部署ELK测试

    一.背景 学习ELK,动手实验. 参考:https://blog.csdn.net/qq_33406938/article/details/80307679 二.环境 虚拟机一台,已安装jdk1.8, ...

  4. Spring-boot01

    本文记录Spring-Boot学习途中的点点滴滴. 其实Spring-Boot出来好长时间了,但是一直没去关注过.之前在我的印象里Spring-Boot好就好在减去了很多XML配置,加入了很多自动配置 ...

  5. Java并发编程 (十) 多线程并发拓展

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一.死锁 1.死锁的定义 所谓的死锁是指两个或两个以上的线程在等待执行的过程中,因为竞争资源而造成的一种 ...

  6. 可以Postman,也可以cURL.进来领略下cURL的独门绝技

    文章已经收录在 Github.com/niumoo/JavaNotes ,更有 Java 程序员所需要掌握的核心知识,欢迎Star和指教. 欢迎关注我的公众号,文章每周更新. cURL 是一个开源免费 ...

  7. Java实现 LeetCode 780 到达终点(逻辑题)

    780. 到达终点 从点 (x, y) 可以转换到 (x, x+y) 或者 (x+y, y). 给定一个起点 (sx, sy) 和一个终点 (tx, ty),如果通过一系列的转换可以从起点到达终点,则 ...

  8. java中Calender类的详细用法(详解)

    一. 如何创建 Calendar 对象 Calendar 是一个抽象类, 无法通过直接实例化得到对象. 因此, Calendar 提供了一个方法 getInstance,来获得一个Calendar对象 ...

  9. Java实现 LeetCode 168 Excel表列名称

    168. Excel表列名称 给定一个正整数,返回它在 Excel 表中相对应的列名称. 例如, 1 -> A 2 -> B 3 -> C ... 26 -> Z 27 -&g ...

  10. Java实现蓝桥杯快乐数

    [问题描述] 判断一个正整数是否是快乐数字? 如果一个数字能够通过有限次快乐变换成为1,则是快乐数字. 快乐变换是对一个数字的每一位的平方数求和. 例如: 对于68 68 => 62+82= 1 ...