1. 使用背景

在前面jstat命令的介绍中,我们知道了可以用它来轻松的了解到线上系统中JVM的各种运行情况和指标。

但是如果有时候发现jvm中新增对象的速度很快,想要知道是什么对象新增这么快;或者我们想要知道在我们的系统中,哪些对象占据了大部分的内存空间。

另外就是,如果系统发生卡顿或者频繁GC等现象,就可能是堆内存出了问题,这个时候就需要借助 Java堆的Dump来查看对象的具体情况

这个时候,就需要使用 jmap命令了,它可以帮助我们了解线上系统jvm中的对象分布情况。

2. jmap的介绍及使用

jmap 中也有很多参数可以实现各种不同的功能,这里就只介绍对于我们日常开发中比较重要的几个用法,其他的可以自行查看。
 

2.1 jmap -histo PID

  • jmap -histo[:live] PID:(添加:live选项只打印存活的对象)执行这个命令会打印出如下信息:
     

这个命令会按照各种对象占用内存空间的大小降序排列,把占用内存最多的对象放在最上面;
打印结果依次为:编号、对象数量、占用内存大小(byte)、class名称。

  • jmap -histo PID | head -n 100: 由于命令会打印所有的对象,经常会占满你的整个linux客户端界面,所以我们可以使用这行命令来查看排在前100位的对象;
  • jmap -histo PID | grep com.test.xxx:或者你只想关注你的系统中的对象,假如你的系统包路径为 com.test.xxx…,就可以使用这行命令来查看只属于你的系统的对象的占比,同样也是从大到小进行排列的;

如果只是将要简单的了解一下当前jvm中的对象内存占用情况,jmap -histo 命令就可以实现了,也非常好用。

2.2 jmap -dump

如果还想要深入的了解堆中各种内存的分布情况,就可以生成一个堆内存快照到文件中去。

  • jmap -dump[:live]:format=b,file=dump.hprof PID:执行这个命令,就会在当前目录下生成一个 dump.hprof文件,也就是把当前时刻的jvm堆内存中的所有对象的快照放入到了这个文件中;
    文件是二进制格式的,不能直接查看,需要使用其他工具(jhat、mat)进行分析;

2.3 jhat

在上面生成的二进制格式的dump文件,可以使用 jhat命令进行打开分析,jhat内置了web服务器,在运行之后会以开启一个端口,让你可以通过浏览器以图形化的方式来分析堆快照。

  • jhat dump.hprof -port 7000:执行这个命令后,就会启动 一个jhat服务器,端口为7000(默认端口,也可以自己指定);你就可以在浏览器上访问当前服务器的7000端口,查看堆内存中对象的分布情况了;

当然,对于dump文件,一般都是使用MAT工具进行分析,MAT工具的使用将在下文继续介绍。