JVM(六)JVM调优分析的一些命令
一、jps【查看进程id】
当我们启动了一个web应用程序时,可以通过jps查看其进程id,接着用各种jdk自带命令优化应用。
使用方式:
二、jmap【查看内存信息,实例个数以及占用内存大小】
查看内存信息
- num :序号
- instances :实例数量
- bytes :占用空间大小
- class name :类名称
- [C :char[]
- [S :short[]
- [I :int[]
- [B :byte[]
- [[I :int[][]
查看堆信息
JVM生成的dump文件分析
我们可以在应用程序执行时设置VM参数,让其生成dump文件,用来分析应用的内存使用情况:
三、jstack【查看栈信息,CPU占用情况】
查看栈线程信息
- Thread-1 :线程名
- prio=5 :优先级=5
- os_prio=0 :操作系统执行的优先级
- tid=0x000000001fa9e000 :java的线程id
- nid=0x2d64 :线程对应的CPU线程标识nid
- java.lang.Thread.State :BLOCKED 线程状态
四、Jinfo【查看Java系统参数和JVM参数】
查看jvm的参数
查看java系统参数
五、Jstat【查看堆内存各部分的使用量】
格式:jstat [-命令选项] [vmid] [间隔时间(毫秒)] [查询次数]
垃圾回收统计
- S0C :第一个幸存区的大小,单位KB
- S1C :第二个幸存区的大小
- S0U :第一个幸存区的使用大小
- S1U :第二个幸存区的使用大小
- EC :伊甸园区的大小
- EU :伊甸园区的使用大小
- OC :老年代大小
- OU :老年代使用大小
- MC :方法区大小(元空间)
- MU :方法区使用大小
- CCSC :压缩类空间大小
- CCSU :压缩类空间使用大小
- YGC :年轻代垃圾回收次数
- YGCT :年轻代垃圾回收消耗时间,单位s
- FGC :老年代垃圾回收次数
- FGCT :老年代垃圾回收消耗时间,单位s
- GCT :垃圾回收消耗总时间,单位s
新生代垃圾回收统计
- S0C :第一个幸存区的大小,单位KB
- S1C :第二个幸存区的大小
- S0U :第一个幸存区的使用大小
- S1U :第二个幸存区的使用大小
- TT :对象在新生代存活的次数
- MTT :对象在新生代存活的最大次数
- DSS :期望的幸存区大小
- EC :伊甸园区的大小
- EU :伊甸园区的使用大小
- YGC :年轻代垃圾回收次数
- YGCT :年轻代垃圾回收消耗时间
老年代垃圾回收统计
- MC :方法区大小,单位KB
- MU :方法区使用大小
- CCSC :压缩类空间大小
- CCSU :压缩类空间使用大小
- OC :老年代大小
- OU :老年代使用大小
- YGC :年轻代垃圾回收次数
- FGC :老年代垃圾回收次数
- FGCT :老年代垃圾回收消耗时间
- GCT :垃圾回收消耗总时间
堆内存统计
- NGCMN :新生代最小容量,单位KB
- NGCMX :新生代最大容量
- NGC :当前新生代容量
- S0C :第一个幸存区大小
- S1C :第二个幸存区的大小
- EC :伊甸园区的大小
- OGCMN :老年代最小容量
- OGCMX :老年代最大容量
- OGC :当前老年代大小
- OC :当前老年代大小
- MCMN :最小元数据容量
- MCMX :最大元数据容量
- MC :当前元数据空间大小
- CCSMN :最小压缩类空间大小
- CCSMX :最大压缩类空间大小
- CCSC :当前压缩类空间大小
- YGC :年轻代gc次数
- FGC :老年代GC次数
新生代内存统计
- NGCMN :新生代最小容量,单位KB
- NGCMX :新生代最大容量
- NGC :当前新生代容量
- S0CMX :最大幸存1区大小
- S0C :当前幸存1区大小
- S1CMX :最大幸存2区大小
- S1C :当前幸存2区大小
- ECMX :最大伊甸园区大小
- EC :当前伊甸园区大小
- YGC :年轻代垃圾回收次数
- FGC :老年代回收次数
老年代内存统计
- OGCMN :老年代最小容量
- OGCMX :老年代最大容量
- OGC :当前老年代大小
- OC :老年代大小
- YGC :年轻代垃圾回收次数
- FGC :老年代垃圾回收次数
- FGCT :老年代垃圾回收消耗时间
- GCT :垃圾回收消耗总时间
六、优化思路
用 jstat gc -pid 命令可以计算出一些关键数据,有了这些数据就可以给自己的系统设置一些初始性的JVM参数,比如堆内存大小,年轻代大小,Eden和Survivor的比例,老年代的大小,大对象的阈值,大龄对象进入老年代的阈值等。
优化思路:尽量让每次Young GC后的存活对象小于Survivor区域的50%,都留存在年轻代里,尽量别让对象进入老年代。尽量减少Full GC的频率,避免频繁Full GC对JVM性能的影响。
年轻代对象增长的速率
可以执行命令 jstat -gc pid 1000 10 (每隔1秒执行1次命令,共执行10次),通过观察EU(eden区的使用)来估算每秒eden大概新增多少对象,如果系统负载不高,可以把频率1秒换成1分钟,甚至10分钟来观察整体情况。
PS:一般系统可能有高峰期和日常期,所以需要在不同的时间分别估算不同情况下对象增长速率。
Young GC的触发频率和每次耗时
知道年轻代对象增长速率我们就能推根据eden区的大小推算出Young GC大概多久触发一次,Young GC的平均耗时可以通过 YGCT/YGC 公式算出,根据结果我们大概就能知道系统大概多久会因为Young GC的执行而卡顿多久。
每次Young GC后有多少对象存活和进入老年代
根据上一步的分析已经大概知道Young GC的频率,假设是每5分钟一次,那么可以执行命令 jstat -gc pid 300000 10 ,观察每次结果eden, survivor和老年代使用的变化情况,在每次gc后eden区使用一般会大幅减少,survivor和老年代都有可能增长,这些增长的对象就是每次Young GC后存活的对象,同时还可以看出每次Young GC后进去老年代大概多少对象,从而可以推算出老年代对象增长速率。
Full GC的触发频率和每次耗时
知道了老年代对象的增长速率就可以推算出Full GC的触发频率了,Full GC的每次耗时可以用公式 FGCT/FGC 计算得出。
七、小问答
Q:突然内存飙升怎么办?
首先用JVM调优工具看看是不是有大量的类生成了,或者是不是有死循环在暂用资源,还可以用jstack命令来监视,找出占用CPU最高的线程堆栈信息。
Q:如何防止代码中的主动gc影响性能呢?
线上系统尽量都带上-XX:DisableExplicitGC参数来使得代码内的System.gc()【会造成多余的full gc】这种代码不生效。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律