JVM 调优

1. 调优工具

  • JDK 工具命令
    • jps: 查看进程
    • jinfo: 查看 jvm 设置信息
    • jstat: 查看类装载情况
    • jmap: 查看内存使用情况,可导出内存镜像 dump 文件,可以使用 MAT 等软件来分析,使用是可能会导致 full GC 或者 OOM
  • JMX(Java Management Extensions)
    • jconsole: 常用查看内存信息
    • visualVM: 采样数据更详细些
  • JMC(java Mission Control): 更强大,一般配合 Flight Recorder 一起使用
  • Btrace
  • 火焰图
  • JProfiler

2. 调优思路

常见场景有 2 种,CPU 过高或内存使用过高。

1. CPU 过高

思路是 查进程->查线程列表->查线程堆栈,可以出现的情况有:

  • 线程本身问题
  • 死锁
  • 频繁 GC

1. 查进程

使用 top 命令,查询所有进程,使用大写 P 键,按照 CPU 使用排序,找到 CPU 过高的进程 PID。

2. 查线程列表

使用 top -Hp PID 命令,查看指定进程内运行的线程状况,-H 表示显示线程信息。查找其中占用较高的几个线程 PID。

3. 查线程堆栈

  1. 查看进程堆栈信息,使用 jstack PID > tmp.txt 查看指定进程所有堆栈信息,并使用上一步中的线程 PID 的十六进制格式,在导出文件中具体对应线程的堆栈信息。
1
2
# 10进制转16进制
printf '%x\n' 654321 # 输出 9fbf1
  1. 对于死锁信息查看,可以使用 jstack -l PID > tmp.txt,在其中搜索 deadlock 信息。
  2. 对于 GC 信息,可以使用 jstat -gcutil PID 1000 ,每隔 1000ms 打印 GC 信息。

jstat

各个区域的使用情况都会以百分比的形式进行显示,在 0.0%~100.0% 之间

  • S0: 表示 survivor space 0 区域的使用情况,即第1个幸存区的使用情况
  • S1: 表示 survivor space 1 区域的使用情况,即第2个幸存区的使用情况
  • E: 表示 eden space 区域的使用情况,即新生代中Eden区的使用情况
  • O: 表示 old space 区域的使用情况,即老年代中的使用情况
  • M: 表示 metaspace 区域的使用情况,即元空间中的使用情况
  • CCS: 表示压缩类空间的使用情况。如果JVM启用了类数据共享(CDS)技术并且开启了压缩类指针(Compressed Class Pointer) 选项,那么就会存在一个称为“压缩类空间”的特殊区域,用于存放共享的类元数据信息
  • YGC: 表示年轻代垃圾回收的次数。年轻代是 JVM 中内存分配的主要区域,垃圾回收在此区域较为频繁
  • YGCT: 表示年轻代垃圾回收所花费的时间总和。通常情况下,年轻代垃圾回收所需时间不应过长,否则可能会导致系统响应变慢或出现卡顿现象
  • FGC: 表示 Full GC(全局垃圾回收) 的次数。Full GC 是对整个Java堆进行清理的垃圾回收过程,较为耗时
  • FGCT: 表示Full GC 所花费的时间总和。Full GC 的执行时间通常比年轻代垃圾回收要长得多,因为它需要处理整个 Java 堆
  • GCT: 表示所有垃圾回收所花费的时间总和,即 YGCT 和 FGCT 的总和

2. 内存使用过高

思路是 查进程->jvm 内存占用,可能出现的情况有:

  • 堆内存占用过大
  • 查询堆栈 dump

1. 查进程

方式与查 CPU 一样,借助 top 查看,可以使用 大写 M 按照内存排序。

2. jvm 内存占用

1. 查看堆情况

通过与 CPU 一致查询方式,查询到频繁的 ygc 并且大量的数据都在老年代没有回收,此时需要分析那些对象占用了内存。使用命令 jmap -histo PID 查询 Java 堆内存中各个对象类型及其数量的统计信息:

jmap

  • num: 参数代表要分析的 Java 进程中的对象编号
  • #instances: 表示 Java 堆内存中对象的数量
  • #bytes: 表示 Java 堆内存中对象占用的总字节数
  • class name: 表示 Java 堆内存中对象所属类名

找到创建比较多的对象,具体分析一下代码中哪些地方创建了的对象为什么没被回收。

1
2
# 用于生成 Java 进程的内存快照文件,hprof 格式,以便进行后续的分析和调试
jmap -dump:format=b,file=heapdump.hprof PID

文件可以通过 Java 虚拟机诊断工具(例如 VisualVM、Jprofile、Eclipse Memory Analyzer 等)进行分析和调试。

2. 查看实际占用

JVM 参数都使用默认的配置,可以使用命令查看实际使用的内存情况,然后再调整 JVM 参数。

1
jmap -heap PID