为了账号安全,请及时绑定邮箱和手机立即绑定

jmap命令的实现原理解析

标签:
Java

简书 占小狼,转载请注明原创出处,谢谢!

当服务发生GC问题时,一般会使用jmap工具进行分析,jmap工具很强大,所以有必要了解它的方方面面。

https://img1.sycdn.imooc.com//5d32752100018c4707380303.jpg

jmap可以做什么?

1、jmap -histo[:live] <pid>

通过histo选项,打印当前java堆中各个对象的数量、大小。
如果添加了live,只会打印活跃的对象。

https://img1.sycdn.imooc.com//5d3275250001374e07190137.jpg

2、jmap -dump:[live,]format=b,file=<filename> <pid>

通过-dump选项,把java堆中的对象dump到本地文件,然后使用MAT进行分析。
如果添加了live,只会dump活跃的对象。

3、jmap -heap <pid>

通过-heap选项,打印java堆的配置情况和使用情况,还有使用的GC算法。

4、jmap -finalizerinfo <pid>

通过-finalizerinfo选项,打印那些正在等待执行finalize方法的对象。

5、jmap -permstat <pid>

通过-permstat选项,打印java堆永久代的信息,包括class loader相关的信息,和interned Strings的信息。

jmap实现原理

通过jmap和jvm之间进行通信,有两种实现方式:attach 和 SA。

attach

attach方式,简单来说就是客户端和服务端之间的通信,客户端发送请求,主要逻辑在服务端执行,jmap相当于客户端,JVM相当于服务端。

在JVM中,有一个叫"Attach Listener"的线程,专门负责监听attach的请求,并执行对应的操作。

比如现在执行"jmap -histo:live 5409",一步一步的实现如下:
1、在Jmap.java类的main函数中,对参数进行解析。
2、解析出来参数中有“-histo:live”,则执行histo方法:

https://img1.sycdn.imooc.com//5d32752c0001566b07090125.jpg

attach方法建立了jmap进程和JVM之间的socket连接,建立过程可以查看笨神的文章JVM Attach机制实现,后续基于该连接进行通信。

因为命令行中添加了[:live]选项,这里的live参数是true。

再看看heapHisto方法

https://img1.sycdn.imooc.com//5d32752f000181d107100366.jpg

executeCommand方法基于之前的socket连接向JVM发送了一条"inspectheap"命令,当然了,还有参数。

虚拟机的"Attach Listener"线程当发现有新的命令时,就拿出来处理它。

命令和具体的函数对应关系如下:

https://img1.sycdn.imooc.com//5d3275320001178a07070299.jpg

和"inspectheap"对应的是heap_inspection方法,实现如下:

https://img1.sycdn.imooc.com//5d3275360001880a07100425.jpg

live_objects_only的值取决于请求中是否有"-live",再jmap中,取决于是否有":live",所以不管是不是添加了":live",都会有STW过程,时间长短而已。

在VM_GC_HeapInspection的doit方法中

https://img1.sycdn.imooc.com//5d32753a0001d05c07210223.jpg

_full_gc的值就是live_objects_only,如果为true,可能会执行一次full gc,清空非活跃的对象,但是可能会因为GC locker,导致跳过本次的GC。

"jmap -dump"实现的原理和"jmap -histo"类似,都是通过attach的方式实现,
attach API的实现方式是:
1、客户端连接到目标JVM,向其发出一个类似“inspectheap”命令;
2、目标JVM接收到命令,执行JVM内相关函数,将收集到的结果以文本形式返回;
3、客户端接收到返回的文本并将其显示出来;

SA

假如执行"jmap -heap 5409",就不会使用attach方式实现了。

在参数解析中,如果参数是"-heap|-heap:format=b|-permstat|-finalizerinfo"中的一种,或者添加了"-F",比如"jmap -histo -F 5409",则使用SA的方式。

https://img1.sycdn.imooc.com//5d536e190001912408880257.jpg

SA方式,和attach方式不同的是,相关的主要逻辑都在SA中实现,从JVM中获取数据即可。

可以大概看下"jmap -heap"的实现,对应的实现类是"HeapSummary",内部通过BugSpotAgent工具类attach到目标VM,更具体的底层细节,可以参考HotSpot Serviceability Agent 实现浅析

执行jmap -heap有些时候可能会导致进程变T,一般是有一个线程在等信号量,这时会block住其它所有线程,可以执行kill -CONT <pid>进行恢复,不过还是强烈建议别执行这个命令


作者:占小狼
链接:https://www.jianshu.com/p/cf118e8f929a


点击查看更多内容
1人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消