Hedley

Stay Hungry, Stay Foolish.

HotSpot JVM 调试大杂烩

此文的 JVM 环境特指 HotSpot JVM

Understanding Garbage Collection

了解 JVM 内存回收机制,以及年轻代、伊甸园、年老代的意义。Full GC 发生很频繁时,关注是否分配内存不足1、死锁、或者内存泄露。

jstat - Statistics Monitoring

一系列调试选项,常用 jstat -gcutil 排查内存问题。

jstack - Stack Trace

了解不同的线程状态。通常用来排查是否有死锁发生,以及找出高 CPU 消耗的线程状态。

  • top -Hp [PID] - 找出进程内最耗费CPU的线程
  • printf "%x\n" [PID] - 得到线程号 TID
  • jstack [PID] | grep [TID] - 观察线程信息

jmap - Memory Map

分析 JVM 的内存状态,是排查内存泄露的关键。

  • jmap -heap [PID] - 进程堆内存使用情况
  • jmap -histo[:live] [PID] | head 15 - 对象占用图。对象占用图粒度很粗,无法获得更详细的对象状态
  • jmap -dump:format=b,file=dump.hprof [PID] - 生成 dump.hprof 文件。执行时间稍长,基于此可进行进一步的精准分析

Eclipse MAT

基于 dump.hprof 进行分析,首选主流工具 Eclipse MATMAT 可以开上帝视角,通过 OQL 精确定位到每个对象,用来做详细的分析挖掘很好用。不过它的缺点也很明显:重量级。如果 dump 文件不大,直接用 MAT 分析没有问题。但现实运行环境中,dump 文件通常很大2,一般需要面临以下问题:从服务器压缩传输到个人机器,压缩和传输的时间成本很高;解压缩后用 MAT 导入,如果个人机器的内存不够,无法进行解析3

内存不够装进 Eclipse 的解决方案

找到 org.eclipse.equinox.launcher_1*.jar 的本地目录,命令行执行生成索引过程:

java -jar /Users/hedley/eclipse/java-neon/Eclipse.app/Contents/Eclipse/plugins/org.eclipse.equinox.launcher_1*.jar -consoleLog -application org.eclipse.mat.api.parse dump.hprof org.eclipse.mat.api:suspects org.eclipse.mat.api:overview org.eclipse.mat.api:top_components 生成报告,其中 org.eclipse.mat.api:suspectsorg.eclipse.mat.api:overvieworg.eclipse.mat.api:top_components 是生成的三个主要模块,可根据需要配置。再用 Eclipse 打开报告目录。

如果以上命令还报内存不足,尝试加参数 -Xmx4g -XX:-UseGCOverheadLimit

OQL2

BHeapSampler

BHeapSampler 是一款轻量级的 JVM 内存分析工具。不,它不单单是轻量级,是羽毛级!如果用 MAT,通常需要把臃肿的 dump.hprof 传到本机进行操作4。而 BHeapSampler 是一个大小只有 26Kjar 包,上传到服务器一行指令即可进行分析。它分析得到的是一张大内存对象引用图,不能进行任何操作与细项查询索引。但是这张重点鲜明的内存图,有时会比 MAT 更击中要害。大写的赞。

  • java -Xmx40g -XX:-UseGCOverheadLimit -jar bheapsampler.jar dump.hprof - 得到 memory_graph.dot
  • 可以用 Graphviz 查看 .dot 文件,装完也可以将 .dot 转为 pdf 格式: /opt/local/bin/dot -Tpdf -omemory_graph.pdf memory_graph.dot
Mac 安装 Graphviz




  1. For old generation space OutOfMemoryErrors, increase -Xms and -Xmx; For permanent generation OutOfMemoryErrors, increase -XX:PermSize and -XX:MaxPermSize

  2. 我曾经分析过的线上压力一般服务器的 dump 在 10G 左右

  3. Eclipse 在导入 dump 文件后,会进行索引分析,占用大量内存。内存不足时会报 OutOfMemoryError

  4. 很少有人在服务器上装 Eclipse 吧?