JVM性能调优


常用命令:jps、jinfo、jstat、jstack、jmap
jps:查看java进程及相关信息
jps -l 输出jar包路径,类全名jps -m 输出main参数jps -v 输出JVM参数

jinfo:查看JVM参数
jinfo 11666jinfo -flags 11666Xmx、Xms、Xmn、MetaspaceSize


jstat:查看JVM运行时的状态信息,包括内存状态、垃圾回收
jstat [option] LVMID [interval] [count]其中LVMID是进程id,interval是打印间隔时间(毫秒),count是打印次数(默认一直打印) option参数解释:-gc 垃圾回收堆的行为统计-gccapacity 各个垃圾回收代容量(young,old,perm)和他们相应的空间统计-gcutil 垃圾回收统计概述-gcnew 新生代行为统计-gcold 年老代和永生代行为统计
jstat -gc 24271(程序运行时的pid)
jstat -class 24271
jstat -compiler 24271
-gc:关注内存和垃圾回收行为,适合分析内存泄漏或 GC 性能问题。
-class:关注类加载行为,适合分析类加载器或内存中的类数量问题。
-compiler:关注 JIT 编译行为,适合分析编译性能或编译失败问题。

jstack:查看JVM线程快照,jstack命令可以定位线程出现长时间卡顿的原因,例如死锁,死循环
jstack [-l] <pid> (连接运行中的进程) option参数解释:-F 当使用jstack <pid>无响应时,强制输出线程堆栈。-m 同时输出java和本地堆栈(混合模式)-l 额外显示锁信息

jmap:可以用来查看内存信息(配合jhat使用)
jmap [option] <pid> (连接正在执行的进程)option参数解释:-heap 打印java heap摘要-dump:<dump-options> 生成java堆的dump文件

 

CPU飙高 | 死循环
我们有个线上应用,单节点在运行一段时间后,CPU 的使用会飙升,一旦飙升,一般怀疑某个业务逻辑的计算量太大,或者是触发了死循环(比如著名的 HashMap 高并发引起的死循环),但排查到最后其实是 GC 的问题。
(1)使用 top 命令,查找到使用 CPU 最多的某个进程,记录它的 pid。使用 Shift + P 快捷键可以按 CPU 的使用率进行排序。
top
(2)再次使用 top 命令,加 -H 参数,查看某个进程中使用 CPU 最多的某个线程,记录线程的 ID。
top -Hp $pid
(3)使用 printf 函数,将十进制的 tid 转化成十六进制。
printf %x $tid
(4)使用 jstack 命令,查看 Java 进程的线程栈。
jstack $pid >$pid.log
(5)使用 less 命令查看生成的文件,并查找刚才转化的十六进制 tid,找到发生问题的线程上下文。
less $pid.log
我们在 jstack 日志搜关键字DEAD,以及中找到了 CPU 使用最多的几个线程id。
可以看到问题发生的根源,是我们的堆已经满了,但是又没有发生 OOM,于是 GC 进程就一直在那里回收,回收的效果又非常一般,造成 CPU 升高应用假死。接下来的具体问题排查,就需要把内存 dump 一份下来,使用 MAT 等工具分析具体原因了。

posted on 2025-06-05 10:34  james-roger  阅读(16)  评论(0)    收藏  举报