JIT中的LogCompilation

Stella981
• 阅读 669

点击上方的****蓝字关注我吧

程序那些事

JIT中的LogCompilation

简介

我们知道在JVM中为了加快编译速度,引入了JIT即时编译的功能。那么JIT什么时候开始编译的,又是怎么编译的,作为一个高傲的程序员,有没有办法去探究JIT编译的秘密呢?答案是有的,今天和小师妹一起带大家来看一看这个编译背后的秘密。

LogCompilation简介

小师妹:F师兄,JIT这么神器,但是好像就是一个黑盒子,有没有办法可以探寻到其内部的本质呢?

追求真理和探索精神是我们作为程序员的最大优点,想想如果没有玻尔关于原子结构的新理论,怎么会有原子体系的突破,如果没有海森堡的矩阵力学,怎么会有量子力学的建立?

JIT的编译日志输出很简单,使用

-XX:+LogCompilation

就够了。

如果要把日志重定向到一个日志文件中,则可以使用

-XX:LogFile=

但是要开启这些分析的功能,又需要使用

-XX:+UnlockDiagnosticVMOptions

 所以总结一下,我们需要这样使用:

-XX:+UnlockDiagnosticVMOptions -XX:+LogCompilation -XX:LogFile=www.flydean.com.log

LogCompilation的使用

根据上面的介绍,我们现场来生成一个JIT的编译日志,为了体现出专业性,这里我们需要使用到JMH来做性能测试。

JMH的全称是Java Microbenchmark Harness,是一个open JDK中用来做性能测试的套件。该套件已经被包含在了JDK 12中。

如果你使用的不是JDK 12,那么需要添加如下依赖:

<dependency>

更多详情可以参考我之前写的:在java中使用JMH(Java Microbenchmark Harness)做性能测试一文。

之前有的朋友说,代码也用图片,看起来好看,从本文之后,我们会尽量把代码也转成图片来展示:

JIT中的LogCompilation

看完我的JMH的介绍,上面的例子应该很清楚了,主要就是做一个累加操作,然后warmup 5轮,测试5轮。

在@Fork注解里面,我们可以配置jvm的参数,为什么我注释掉了呢?因为我发现在jvmArgsPrepend中的-XX:LogFile是不生效的。

没办法,我只好在运行配置中添加:

JIT中的LogCompilation

运行之后,你就可以得到输出的编译日志文件。

解析LogCompilation文件

小师妹:F师兄,我看了一下生成的文件好复杂啊,用肉眼能看得明白吗?

别怕,只是内容的多一点,如果我们细细再细细的分析一下,你会发现其实它真的非常非常……复杂!

其实写点简单的小白文不好吗?为什么要来分析这么复杂,又没人看,看了也没人懂的JVM底层…..

大概,这就是专业吧!

LogCompilation文件其实是xml格式的,我们现在来大概分析一下,它的结构,让大家下次看到这个文件也能够大概了解它的重点。

JIT中的LogCompilation

首先最基本的信息就是JVM的信息,包括JVM的版本,JVM运行的参数,还有一些properties属性。

我们收集到的日志其实是分两类的,第一类是应用程序本身的的编译日志,第二类就是编译线程自己内部产生的日志。

第二类的日志会以hs_c*.log的格式存储,然后在JVM退出的时候,再将这些文件跟最终的日志输出文件合并,生成一个整体的日志文件。

比如下面的两个就是编译线程内部的日志:

JIT中的LogCompilation

<thread_logfile thread='22275' filename='/var/folders/n5/217y_bgn49z18zvjch907xb00000gp/T//hs_c22275_pid83940.log'/>

<thread_logfile thread='41731' filename='/var/folders/n5/217y_bgn49z18zvjch907xb00000gp/T//hs_c41731_pid83940.log'/>

JIT中的LogCompilation

上面列出了编译线程的id=22275,如果我们顺着22275找下去,则可以找到具体编译线程的日志:

JIT中的LogCompilation

<compilation_log thread='22275'>...</compilation_log>

JIT中的LogCompilation

上面由compilation_log围起来的部分就是编译日志了。

接下来的部分表示,编译线程开始执行了,其中stamp表示的是启动时间,下图列出了一个完整的编译线程的日志:

JIT中的LogCompilation

JIT中的LogCompilation

<start_compile_thread name='C2 CompilerThread0' thread='22275' process='83940' stamp='0.058'/>

JIT中的LogCompilation

接下来描述的是要编译的方法信息:

JIT中的LogCompilation

<task compile_id='10' method='java.lang.Object ()V' bytes='1' count='1409' iicount='1409' stamp='0.153'>

JIT中的LogCompilation

上面列出了要编译的方法名,compile_id表示的是系统内部分配的编译id,bytes是方法中的字节数,count表示的是该方法的调用次数,注意,这里的次数并不是方法的真实调用次数,只能做一个估计。

iicount是解释器被调用的次数。

task执行了,自然就会执行完成,执行完成的内容是以task_done标签来表示的:

JIT中的LogCompilation

<task_done success='1' nmsize='120' count='1468' stamp='0.155'/>

JIT中的LogCompilation

其中success表示是否成功执行,nmsize表示编译器编译出来的指令大小,以byte为单位。如果有内联的话,还有个inlined_bytes属性,表示inlined的字节个数。

JIT中的LogCompilation

JIT中的LogCompilation

type表示的是方法的返回类型。

JIT中的LogCompilation

JIT中的LogCompilation

klass表示的是实例和数组类型。

JIT中的LogCompilation

<method id='1148' holder='1030' name='' return='1025' flags='1' bytes='1' compile_id='1' compiler='c1' level='3' iicount='1419'/>

JIT中的LogCompilation

method表示执行的方法,holder是前面的klass的id,表示的是定义该方法的实例或者数组对象。method有名字,有
return,return对应的是上面的type。

flags表示的是方法的访问权限。

接下来是parse,是分析阶段的日志:

JIT中的LogCompilation

JIT中的LogCompilation

上面有parse的方法id。uses是使用次数。

JIT中的LogCompilation

JIT中的LogCompilation

bc是byte Count的缩写,code是byte的个数,bci是byte code的索引。

JIT中的LogCompilation

JIT中的LogCompilation

dependency分析的是类的依赖关系,type表示的是什么类型的依赖,ctkx是依赖的context class。

我们注意有的parse中,可能会有uncommon_trap:

JIT中的LogCompilation

<uncommon_trap bci='10' reason='unstable_if' action='reinterpret' debug_id='0' comment='taken never'/>

JIT中的LogCompilation

怎么理解uncommon_trap呢?字面上意思就是捕获非常用的代码,就是说在解析代码的过程中发现发现这些代码是uncommon的,然后解析产生一个uncommon_trap,不再继续进行了。

它里面有两个比较重要的字段,reason表示的是被标记为uncommon_trap的原因。action表示的出发uncommon_trap的事件。

有些地方还会有call:

JIT中的LogCompilation

<call method='1150' count='5154' prof_factor='1.000000' inline='1'/>

JIT中的LogCompilation

call的意思是,在该代码中将会调用其他的方法。count是执行次数。

总结

复杂的编译日志终于讲完了,可能讲的并不是很全,还有一些其他情况这里并没有列出来,后面如果遇到了,我再添加进去。

JIT中的LogCompilation

作者小F,金融科技从业多年,懂技术又懂金融,主攻Java和区块链方向,篇篇都是用心之作,笔耕不辍,持续更新!

微信号 : 程序那些事

● 扫码关注我吧

喜欢本篇文章?帮忙点个「在看」再走吧

JIT中的LogCompilation

本文分享自微信公众号 - 程序那些事(flydean-tech)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
2021 最顶级 React 组件库推荐
点上方蓝字关注公众号「前端从进阶到入院」作者丨MaxRozen译者丨王强策划丨小智AntDesign!(https://oscimg.oschina.net/oscnet/a85c35f23bd04e5da6a1e5e68a24119b.png)项目链接:AntDesignh
Stella981 Stella981
3年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
可莉 可莉
3年前
2021 最顶级 React 组件库推荐
点上方蓝字关注公众号「前端从进阶到入院」作者丨MaxRozen译者丨王强策划丨小智AntDesign!(https://oscimg.oschina.net/oscnet/a85c35f23bd04e5da6a1e5e68a24119b.png)项目链接:AntDesignh
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
35岁是技术人的天花板吗?
35岁是技术人的天花板吗?我非常不认同“35岁现象”,人类没有那么脆弱,人类的智力不会说是35岁之后就停止发展,更不是说35岁之后就没有机会了。马云35岁还在教书,任正非35岁还在工厂上班。为什么技术人员到35岁就应该退役了呢?所以35岁根本就不是一个问题,我今年已经37岁了,我发现我才刚刚找到自己的节奏,刚刚上路。
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这