小师妹学jvm之:jit中的printcompilation(代码片段)

flydean flydean     2022-11-30     452

关键词:

简介

上篇文章我们讲到了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之:cacheline对代码性能的影响(代码片段)

...sembly来理解我们之前不能理解的问题。一个奇怪的现象小师妹:F师兄,之前你讲了那么多JVM中JIT在编译中的性能优化,讲真的,在工作中我们真的需要知道这些东西吗?知道这些东西对我们的工作有什么好处吗 查看详情

小师妹学jvm之:逃逸分析和tlab(代码片段)

...多线程的环境中,如何提升内存的分配效率呢?快来跟小师妹一起学习TLAB技术吧。逃逸分析和栈上分配小师妹:F师兄,从前大家都说对象是在堆中分配的,然后我就 查看详情

小师妹学jvm之:jvm的架构和执行过程(代码片段)

...个不同操作系统中运行的机器代码并运行。今天我们和小师妹一起走进java的核心JVM,领略java在设计上的哲学。JVM是一种标准小师妹:F师兄,经常听到有人说hotspotVM,这 查看详情

小师妹学javaio之:文件读取那些事

...读取的方式按字节读取的方式寻找出错的行数总结简介小师妹最新对javaIO中的reader和stream产生了一点点困惑,不知道到底该用哪一个才对,怎么读取文件才是正确的姿势呢?今天F师兄现场为她解答。字符和字节小师妹最近很迷... 查看详情

小师妹学javaio之:文件编码和字符集unicode

...件编码解决Properties中的乱码真.终极解决办法总结简介小师妹一时兴起,使用了一项从来都没用过的新技能,没想却出现了一个无法解决的问题。把大象装进冰箱到底有几步?乱码的问题又是怎么解决的?快来跟F师兄一起看看吧... 查看详情

小师妹学javaio之:文件编码和字符集unicode

...件编码解决Properties中的乱码真.终极解决办法总结简介小师妹一时兴起,使用了一项从来都没用过的新技能,没想却出现了一个无法解决的问题。把大象装进冰箱到底有几步?乱码的问题又是怎么解决的?快来跟F师兄一起看看吧... 查看详情

小师妹学javaio之:trywith和它的底层原理

...用trywithresourcetrywithresource的原理自定义resource总结简介小师妹是个java初学者,最近正在学习使用javaIO,作为大师兄的我自然要给她最给力的支持了。一起来看看她都遇到了什么问题和问题是怎么被解决的吧。IO关闭的问题这一天... 查看详情

小师妹学javaio之:trywith和它的底层原理

...用trywithresourcetrywithresource的原理自定义resource总结简介小师妹是个java初学者,最近正在学习使用javaIO,作为大师兄的我自然要给她最给力的支持了。一起来看看她都遇到了什么问题和问题是怎么被解决的吧。IO关闭的问题这一天... 查看详情

jvm系列之:jit中的virtualcall接口(代码片段)

...解了VirtualCall的定义并举例分析了VirtualCall在父类和子类中的优化。JIT对类可以进行优化,那么对于interface可不可以做同样的优化么?一起来看看吧。最常用的接口ListList应该是大家最最常用的接口了,我想这个大家应该不会反驳... 查看详情

jvm中栈的frames详解

...的栈到底是怎么工作的呢?快来一起看看吧。JVM中的栈小师妹:F师兄,JVM为每个线程的运行都分配了一个栈,这个栈到底是怎么工作的呢?小师妹,我们先看 查看详情

jvm中的jit

 JVM中的JIT     介绍Java虚拟机的文章或者书籍总会提到Java虚拟机中的JIT编译器,可是JIT编译器到底是什么?为什么需要JIT编译呢?JIT编译器,是JustInTime编译的意思,又称即时编译。 Java程序是先从源代... 查看详情

jvm之方法区(代码片段)

...ss/method/field等元数据对象:字节码加载之后,JVM会根据其中的内容,为这个类生成Class/Method/Field等对象,它们用于描述一个类,通常在反射中用的比较多。不同于存储在堆中的java实例对象,这两种对象存储在方法区中。(3)stat... 查看详情

jvm调优之选择步骤

1.选择JVM运行模式  a.Client模式:启动快,占用内存少,JIT编译器生成代码的速度也更快。  b.Server模式:提供了更复杂的生成代码优化功能,这个功能对服务器应用而言尤其重要。大多数Server模式的JIT的编译优化都要消耗额... 查看详情

jvm之jvm初探

JVM初探JVM执行文件类装入子系统执行引擎垃圾回收器堆中的内存回收方法区中的内存回收关于回收的那些事JVM执行文件JVM执行的文件为class文件,这个执行文件是什么意思呢,就是虚拟机能够识别的文件,类加载器加... 查看详情

jit

...达式消除2.方法内联:JIT会将被调用的方法直接用方法体中的代码代替,减少了方法调用过程中的压栈出栈。3.jdk7后默认开启逃逸分析,逃逸是指当一个对象在方法中被定义,而它能被外部方法引用。  逃逸分析包括:全... 查看详情

学习-jvm命令(代码片段)

...计gcoldcapacity:年老代行为统计gcpermcapacity:永生代行为统计printcompilation:HotSpot编译方法统计LVMID:本地虚拟机进程ID[interval]:连续输出的时间间隔[count]:连续输出的次数option参数详解-class监视类装载、卸载数量、总空间以及耗费的时间$... 查看详情

jvm--12---执行引擎----解释器jit编译器

...可参考右边的帮助文档文章目录执行引擎JVM的主要任务JVM中的执行引擎充当了将高级语言翻译为机器语言的翻译者。执行引擎的工作流程Java代码编译和执行过程Java代码编译Java源代码==>JVM字节码Java字节码的执行JVM字节码... 查看详情

公司发的小师妹问我java中的线程池,这么讲可还行?(代码片段)

文章目录前言一、线程池的实现原理1、当提交一个任务到线程池时,线程池的处理流程以上流程的图解2、`ThreadPoolExecutor`执行`executor()`方法的`四种`情况3、线程池里的线程执行任务分两种情况二、线程池的... 查看详情