欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

深入理解jmap命令:揭示Java虚拟机内存使用详析

最编程 2024-02-10 15:29:23
...

1、jmap命令基本概述

jmap命令是一个可以输出所有内存中对象的工具,甚至可以将VM 中的heap,以二进制输出成文本。

打印出某个java进程(使用pid)内存内的,所有‘对象’的情况(如:产生那些对象,及其数量)。

64位机上使用需要使用如下方式:

jmap -J-d64 -heap pid

2、命令格式

jmap [option] <pid>
        (to connect to running process) 连接到正在运行的进程

jmap [option] <executable <core>
        (to connect to a core file)     连接到核心文件

jmap [option] [server_id@]<remote server IP or hostname>
        (to connect to remote debug server) 连接到远程调试服务

3、参数说明

就是替换[option]位置的参数

1、 -dump

1、 -dump:[live,]format=b,file=<filename> 使用hprof二进制形式,输出jvm的heap内容到文件=. live子选项是可选的,假如指定live选项,那么只输出活的对象到文件。

命令:

jmap -dump:live,format=b,file=myjmapfile.txt 19570

结果:

image

即可在/root目录打开myjmapfile.txt文件。

当然,file=后面也可以指定文件存放的目录,就可以在指定目录查看文件了。

2、 -finalizerinfo

2、 -finalizerinfo 打印正等候回收的对象的信息

命令:

jmap -finalizerinfo 3772
image

结果:
Number of objects pending for finalization: 0 (等候回收的对象为0个)

3、 -heap

3、 -heap 打印heap的概要信息,GC使用的算法,heap(堆)的配置及JVM堆内存的使用情况.

命令:

jmap -heap 19570

结果:


image.png

4、 -histo

4、 -histo[:live] 打印每个class的实例数目,内存占用,类全名信息. VM的内部类名字开头会加上前缀”*”. 如果live子参数加上后,只统计活的对象数量。

命令:

jmap -histo:live 19570

采用jmap -histo pid>a.log日志将其保存,在一段时间后,使用文本对比工具,可以对比出GC回收了哪些对象。

jmap -dump:format=b,file=outfile 3024可以将3024进程的内存heap输出出来到outfile文件里,再配合MAT(内存分析工具)。

5、 -permstat

5、 -permstat 打印classload和jvm heap长久层的信息. 包含每个classloader的名字,活泼性,地址,父classloader和加载的class数量. 另外,内部String的数量和占用内存数也会打印出来.

命令:

jmap -permstat 19570

jmap实现原理

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

1、attach

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

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

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


image.png

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

2、SA

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

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


image.png

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

可以大概看下"jmap -heap"的实现,对应的实现类是"HeapSummary",内部通过BugSpotAgent工具类attach到目标VM

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