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. 查线程堆栈
- 查看进程堆栈信息,使用
jstack PID > tmp.txt
查看指定进程所有堆栈信息,并使用上一步中的线程 PID 的十六进制格式,在导出文件中具体对应线程的堆栈信息。
1 | 10进制转16进制 |
- 对于死锁信息查看,可以使用
jstack -l PID > tmp.txt
,在其中搜索 deadlock 信息。 - 对于 GC 信息,可以使用
jstat -gcutil PID 1000
,每隔 1000ms 打印 GC 信息。
各个区域的使用情况都会以百分比的形式进行显示,在 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 堆内存中各个对象类型及其数量的统计信息:
num
: 参数代表要分析的 Java 进程中的对象编号#instances
: 表示 Java 堆内存中对象的数量#bytes
: 表示 Java 堆内存中对象占用的总字节数class name
: 表示 Java 堆内存中对象所属类名
找到创建比较多的对象,具体分析一下代码中哪些地方创建了的对象为什么没被回收。
1 | 用于生成 Java 进程的内存快照文件,hprof 格式,以便进行后续的分析和调试 |
文件可以通过 Java 虚拟机诊断工具(例如 VisualVM、Jprofile、Eclipse Memory Analyzer 等)进行分析和调试。
2. 查看实际占用
JVM 参数都使用默认的配置,可以使用命令查看实际使用的内存情况,然后再调整 JVM 参数。
1 | jmap -heap PID |