95

jmap命令的实现原理解析

 6 years ago
source link: http://www.jianshu.com/p/cf118e8f929a?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
0.7622017.12.16 07:39:22字数 1,103阅读 10,403

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

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

webp

jmap可以做什么?

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

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

cf118e8f929a?utm_source=tuicool&utm_medium=referral
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方法:

cf118e8f929a?utm_source=tuicool&utm_medium=referral

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

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

再看看heapHisto方法

cf118e8f929a?utm_source=tuicool&utm_medium=referral

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

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

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

cf118e8f929a?utm_source=tuicool&utm_medium=referral

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

cf118e8f929a?utm_source=tuicool&utm_medium=referral

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

在VM_GC_HeapInspection的doit方法中

cf118e8f929a?utm_source=tuicool&utm_medium=referral

_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、客户端接收到返回的文本并将其显示出来;

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

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

webp

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

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

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK