卖不甜枣 发表于 2025-4-6 21:16:16

JVM监控

目录
一、下令行指令
1、jps:查看 Java 进程状态
2、jinfo:查看JVM参数
3、jstat:监控GC、类加载、编译环境
4、jstack:抓取线程快照
5、jmap:天生堆转储文件
6、jcmd:整合工具
二、可视化监控
1、Jconsole(JDK自带)
2、MAT(Memory Analyzer Tool):分析堆转储文件
3、Arthas:在线诊断工具(动态查看类加载、方法执行耗时)
三、GC日记
1、启用GC日记
2、GC日记分析
3、日记分析工具
3.1 GCViewer(离线分析工具)
3.2 GCEasy(在线分析工具)

一、下令行指令

监控流程:先用 jps 定位进程,jstat 分析 GC,jstack 查线程,jmap 抓堆快照。
1、jps:查看 Java 进程状态

用途:快速查看当前运行的 Java 进程及其进程 ID(PID)、主类名、JVM 启动参数等
常用下令:
jps -l      # 显示进程id、主类全名或 JAR 路径
jps -v      # 显示进程id、JVM 启动参数(如 -Xms、-Xmx)
jps -m      # 显示进程id、传递给 main() 方法的参数 关键输出:输出 PID 和主类名称,便于后续工具(如 jstack、jmap)定位目标进程
2、jinfo:查看JVM参数

用途:查看JVM参数或动态修改 JVM 参数(仅限支持动态调解的参数)
常用下令:
jinfo -flags <pid>            # 查看所有 JVM 参数-flags 打印所有参数
jinfo -flag MaxHeapSize <pid> # 查看最大堆内存设置-flag 打印指定名称的参数
jinfo -flag +PrintGC <pid>    # 动态开启 GC 日志打印-flag [+|-] 打开或关闭参数 -flag = 设置参数 留意:部门参数(如堆大小)需重启生效,动态修改需审慎
常用JVM参数:
-Xms:初始堆大小,默认为物理内存的1/64(<1GB);默认(MinHeapFreeRatio参数可以调整)空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制

-Xmx:最大堆大小,默认(MaxHeapFreeRatio参数可以调整)空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制

-Xmn:新生代的内存空间大小,注意:此处的大小是(eden+ 2 survivor space)。与jmap -heap中显示的New gen是不同的。整个堆大小=新生代大小 + 老生代大小 + 永久代大小。在保证堆大小不变的情况下,增大新生代后,将会减小老生代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。

-XX:SurvivorRatio:新生代中Eden区域与Survivor区域的容量比值,默认值为8。两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10。

-Xss:每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。应根据应用的线程所需内存大小进行适当调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。一般小的应用, 如果栈不是很深, 应该是128k够用的,大的应用建议使用256k。这个选项对性能影响比较大,需要严格的测试。和threadstacksize选项解释很类似,官方文档似乎没有解释,
在论坛中有这样一句话:"-Xss ``is translated ``in a VM flag named ThreadStackSize”一般设置这个值就可以了。

-XX:PermSize:设置永久代(perm gen)初始值。默认值为物理内存的1/64。

-XX:MaxPermSize:设置持久代最大值。物理内存的1/4。
3、jstat:监控GC、类加载、编译环境

JVM Statistics Monitoring Tool:JVM统计监视工具
用途:实时监控 JVM 运行时状态,包括垃圾回收(GC)、类加载、JIT 编译等统计信息
常用下令:
jstat -gcutil <pid> 1000 5    # 每 1 秒打印一次 GC 各区域使用百分比,共 5 次 https://i-blog.csdnimg.cn/direct/fa91a39951c24d5183933ff4cba4d2b1.png
字段解释:
S0 survivor0使用百分比
S1 survivor1使用百分比
E Eden区使用百分比
O 老年代使用百分比
M 元数据区使用百分比
CCS 压缩使用百分比
YGC 年轻代垃圾回收次数
YGCT 年轻代垃圾回收消耗时间(单位:秒)
FGC Full GC垃圾回收次数
FGCT Full GC垃圾回收消耗时间(单位:秒)
GCT 垃圾回收消耗总时间(单位:秒)
jstat -gc <pid>   # 显示堆内存各区域(Eden/Survivor/Old)的实际容量和使用量 https://i-blog.csdnimg.cn/direct/f9c2dd439e424d75bf57864eb3ff08d3.png
gc和-gcutil参数类似,只不外输出字段不是百分比,而是现实的值。
字段解释:
S0C survivor0大小
S1C survivor1大小
S0U survivor0已使用大小
S1U survivor1已使用大小
EC Eden区大小
EU Eden区已使用大小
OC 老年代大小
OU 老年代已使用大小
MC 方法区大小
MU 方法区已使用大小
CCSC 压缩类空间大小
CCSU 压缩类空间已使用大小
YGC 年轻代垃圾回收次数
YGCT 年轻代垃圾回收消耗时间(单位:秒)
FGC Full GC垃圾回收次数
FGCT Full GC垃圾回收消耗时间(单位:秒)
GCT 垃圾回收消耗总时间(单位:秒)
jstat -class <pid>       # 显示类加载/卸载数量及耗时 https://i-blog.csdnimg.cn/direct/fb33af0fe60c4ef5a4a69739319913c6.png
关键指标:
    YGC/YGCT:年轻代 GC 次数和耗时。
    FGC/FGCT:Full GC 次数和耗时。
    O:老年代使用百分比
4、jstack:抓取线程快照

用途:天生线程快照,定位死锁、线程壅闭或 CPU 占用过高问题
常用下令:
jstack -l <pid>         # 显示线程堆栈及锁信息
jstack -F <pid>         # 强制生成快照(适用于进程无响应) 关键输出:
    BLOCKED:线程因锁壅闭。
    WAITING:线程处于等待状态(如 Object.wait())。
    deadlock:死锁
示例:cpu占用过高问题(快速查看热门方法)
1> 通过下令 top -Hp <pid> 找到高 CPU 线程
top -H -p <pid>         # 查看线程 CPU 占用 2> 将线程id转换为16进制
printf "%x\n" <线程ID># 将线程 ID 转为十六进制 3> 使用 jstack -l <pid>查看进程快照,在快照中找到nid=16进制的线程id的信息,并分析对应代码
jstack <pid> > thread_dump.txt
grep <十六进制线程ID> thread_dump.txt# 定位线程栈 5、jmap:天生堆转储文件

用途:天生堆转储快照(Heap Dump),分析内存泄漏或对象分布
jmap -dump:live,format=b,file=heap.hprof <pid># 生成存活对象的堆转储文件
                                          # live 只转储存活的对象,如果没有指定则转储所有对象
                                          # format=b 二进制格式
                                          # file= 转储文件到
jhsdb jmap --heap --pid <pid># 显示堆内存配置(GC 算法、分代大小等)
jmap -histo <pid>            # 统计堆中对象数量及占用内存(按类排序) 调优场景:联合 MAT 或 jhat(JDK 9+ 已废弃) 分析内存泄漏、大对象问题
6、jcmd:整合工具

用途:多功能工具,整合了 jps、jstat、jmap 等功能
jcmd <pid> GC.run            # 手动触发 GC
jcmd <pid> VM.native_memory    # 显示本地内存使用情况
jcmd <pid> help                # 列出支持的所有命令 优势:一条下令替换多个工具,适合脚本化监控

二、可视化监控

1、Jconsole(JDK自带)

功能:监控堆内存、线程、类加载、CPU 使用率等基础指标,支持本地和长途连接
本地监控:直接双击 ${JAVA_HOME}/bin/jconsole.exe
长途监控:在win上,连接Linux上的JDK
1> 启动 Java 应用时开启 JMX 长途监控
在 Linux 上运行 Java 步伐时,需添加以下参数:
java -Dcom.sun.management.jmxremote \
   -Dcom.sun.management.jmxremote.port=9999 \          # JMX 服务监听端口
   -Dcom.sun.management.jmxremote.authenticate=false \# 禁用认证(测试用)
   -Dcom.sun.management.jmxremote.ssl=false \          # 禁用 SSL(测试用)
   -Djava.rmi.server.hostname=<Linux服务器IP> \      # 服务器公网IP或域名
   -jar your-app.jar 2> 确保 Linux 防火墙允许 JMX 端口(如 9999)的入站流量:
# 如果使用 iptables
sudo iptables -A INPUT -p tcp --dport 9999 -j ACCEPT
sudo service iptables save && sudo service iptables restart

# 如果使用 firewalld(CentOS/RHEL)
sudo firewall-cmd --zone=public --add-port=9999/tcp --permanent
sudo firewall-cmd --reload 3> 打开win上的 ${JAVA_HOME}/bin/jconsole.exe 进行连接
https://i-blog.csdnimg.cn/direct/a8e84ee28d59442fb6f2b354619717d1.png
https://i-blog.csdnimg.cn/direct/2fb889ddfdbe4000a2e384dbaf336ba1.png
2、MAT(Memory Analyzer Tool):分析堆转储文件

功能:分析堆转储文件(Heap Dump),定位内存泄漏、大对象问题
1> 下载与安装
下载地址:MAT官网下载
解压安装:


[*] 下载后解压到任意目录(无需安装步伐)。
[*] 启动方式:

[*] Windows: 运行 MemoryAnalyzer.exe
[*] macOS/Linux: 运行 mat 脚本(位于解压后的根目录)

配置 JDK 路径(可选)
如果默认 JDK 版本不兼容(需 Java 8+),可修改 MemoryAnalyzer.ini 文件,添加:
-vm
C:\Program Files\Java\jdk-17\bin\javaw.exe# 替换为你的 JDK 路径 2> 天生堆转储文件(Heap Dump)
方法 1:使用 jmap 工具
jmap -dump:format=b,file=heapdump.hprof <pid># <pid> 为目标 Java 进程的 ID 方法 2:JVM 参数自动天生
在 Java 应用启动时添加参数,当发生 OutOfMemoryError 时自动天生堆转储
java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./heapdump.hprof -jar app.jar 3> 使用 MAT 分析堆转储
步骤 1:打开堆转储文件

[*] 启动 MAT,点击 File > Open Heap Dump,选择 .hprof 文件。
[*] MAT 会自动剖析并天生分析陈诉。
步骤 2:分析内存泄漏
Leak Suspects Report(泄漏怀疑陈诉)


[*] 默认天生的陈诉中会列出可能的内存泄漏对象(按占用内存排序)。
[*] 点击 Details 查看对象引用链,定位到详细代码位置。
https://i-blog.csdnimg.cn/direct/86c2e15a53284bf58dd69a698382c1f6.png

Histogram(直方图)


[*] 查看所有类的实例数和内存占用:

[*] 按类名筛选(支持正则表达式)。
[*] 右键点击类名,选择 Merge Shortest Paths to GC Roots,查看哪些 GC Root 引用了这些对象。

https://i-blog.csdnimg.cn/direct/9a8cd9deffe1494a90f5cf59eef75b6f.png
Dominator Tree(支配树)


[*] 表现占用内存最多的对象及其引用关系,查找未开释的引用。
[*] 快速定位内存瓶颈。
https://i-blog.csdnimg.cn/direct/3242ece2270c44a8bcafff191e475275.png
https://i-blog.csdnimg.cn/direct/34e70bb519ab497485cf2d669ec43e03.png
更多可参考:深度讲解MAT

3、Arthas:在线诊断工具(动态查看类加载、方法执行耗时)

功能:在线诊断工具,可以或许在不重启应用的环境下快速定位生产环境中的性能问题、代码逻辑非常和运行状态监控
1> 安装与启动
# 下载并启动 Arthas(自动检测本地 Java 进程)
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar 选择要监控的项目
https://i-blog.csdnimg.cn/direct/cba8020695fc4717a9c66886a9e40e34.png
退出下令
stop 2> 核心功能和下令
# 1、实时监控与系统状态
# dashboard:实时监控线程、内存、GC、类加载等核心指标
dashboard -i 2000# 每2秒刷新一次

# sysenv/sysprop:查看 JVM 环境变量和系统属性
sysprop java.version# 查看 Java 版本


# 2、线程与堆栈分析
thread   # 查看所有线程状态
thread -n 3# 显示前3个高 CPU 线程
thread <线程ID>   # 查看线程完整堆栈
thread -b       # 检测死锁(Blocked 线程)
# heapdump:生成堆转储文件,结合 MAT 分析
heapdump /tmp/heapdump.hprof# 导出堆转储
# vmtool:强制触发 GC 或查看对象分布
vmtool --action getInstances --className com.example.MyCache --limit 10# 查看 MyCache 实例


# 3、类与方法诊断
# jad:反编译类文件,查看源码(支持动态修改后的代码)
jad com.example.MyService# 反编译指定类
# mc/redefine 热更新代码(无需重启应用)
mc -c <ClassLoaderHash> /tmp/MyService.java# 1. 修改源码后编译为 .class 文件
redefine /tmp/MyService.class    # 2. 重新加载类

# watch:监控方法入参、返回值、异常和耗时
watch com.example.MyService getUserInfo "{params, returnObj}" -x 3# 打印参数和返回值,深度 3
# trace:追踪方法调用链路及耗时
trace com.example.MyService processOrder '#cost > 50'# 只显示耗时超过 50ms 的调用
# stack:查看某个方法的调用路径
stack com.example.MyService validateUser# 显示调用链
# monitor:统计方法调用次数、成功率和平均耗时
monitor -c 5 com.example.MyService queryData# 每 5 秒统计一次



# 4、性能分析与火焰图
# profiler:生成 CPU 或内存火焰图,定位性能瓶颈
profiler start          # 开始采样
profiler stop --format svg -o /tmp/flamegraph.svg# 生成 SVG 格式火焰图


# 5、安全关闭 Arthas 服务,避免残留
stop# 退出并清理 Arthas 资源  3> 常见案例
案例1:接口超时分析
# 1. 查看高耗时方法
trace com.example.OrderService createOrder '#cost > 1000'

# 2. 监控方法参数和返回值
watch com.example.OrderService queryInventory "{params, returnObj}" -x 2

# 3. 生成火焰图定位 CPU 热点
profiler start
profiler stop -f /tmp/order_flame.svg 案例2:动态修复配置
# 1. 查看当前配置值
ognl '@com.example.Config@get("timeout")'

# 2. 动态修改配置(需确保类可热更新)
ognl '@com.example.Config@set("timeout", 5000)' 官方文档:Arthas用户手册
保举博客:Arthas使用教程(8大分类)

三、GC日记

GC日记记录了每一次的GC的执行时间和执行结果,通太过析GC日记可以优化堆设置和GC设置,大概改进应用步伐的对象分配模式。
调优重点:联合 GC 日记(-Xloggc)和堆转储文件,优化内存分配与回收策略
1、启用GC日记

JDK8及之前:
java -XX:+PrintGCDetails \
   -XX:+PrintGCDateStamps \
   -XX:+PrintGCApplicationStoppedTime \
   -XX:+UseGCLogFileRotation \
   -XX:NumberOfGCLogFiles=5 \
   -XX:GCLogFileSize=10M \
   -Xloggc:/var/log/gc.log \
   -jar app.jar 参数阐明:
-XX:+PrintGCDetails:打印 GC 详细信息(如回收地域、耗时)。
-XX:+PrintGCDateStamps:添加时间戳(便于分析时序)。
-Xloggc:gc.log:将日记输出到 gc.log 文件。  
-XX:NumberOfGCLogFiles:保存最多 5 个日记文件。
-XX:GCLogFileSize:每个文件最大 10MB,凌驾后滚动。
-XX:+PrintGCApplicationStoppedTime:打印 GC 导致的停顿时间
-XX:+PrintHeapAtGC:输出 GC 前后的堆内存详情

JDK9及更高版本:
java -Xlog:gc*=info:file=/var/log/gc.log:time,uptime,level,tags:filecount=5,filesize=10M \
   -jar app.jar 参数阐明:
gc*:记录所有 GC 相关事件。
file=gc.log:输出到文件 gc.log。
time:添加时间戳(格式:UTC 时间)。
filecount=5,filesize=10M:最多保存 5 个文件,每个 10MB。
gc=debug:设置日记级别为 debug(更详细)。
tags:表现事件范例(如 gc,heap)。
-Xlog:gc*:stdout -Xlog:gc*:file=gc.log:多目标输出(同时输出到控制台和文件)

验证GC日记是否生效
tail -f /var/log/gc.log# 实时查看日志内容
2、GC日记分析

Young GC 日记示例(G1 网络器)
GC(10) Pause Young (G1 Evacuation Pause)
Heap: 1024M->512M(2048M), 0.025 secs
Eden: 800M->0M(1024M)
Survivors: 128M->128M(128M)
Old: 256M->512M(1024M)
User=0.02s Sys=0.00s Real=0.03s 关键字段:
GC(10):第 10 次 GC。
Pause Young:Young GC 范例。
Heap:堆内存变革(回收前 -> 回收后,堆总容量)。
Eden/Survivors/Old:各地域内存变革。
Real=0.03s:现实停顿时间(STW)。

Full GC 日记示例(CMS 网络器)
GC(20) Pause Full (Allocation Failure)
Heap before GC: 2048M(2048M)->1024M(2048M), 0.500 secs
Metaspace: 256M->256M(512M)
User=0.45s Sys=0.05s Real=0.50s 关键字段:
Pause Full:Full GC 范例。
Allocation Failure:触发原因(分配失败)。
Real=0.50s:较长的停顿时间(需警惕)。
手动分析 GC 日记的步骤
1>. 统计 GC 频率和耗时
Young GC 频率:统计日记中 Pause Young 出现的次数,结适时间戳盘算平均间隔。
Full GC 次数:若频繁出现 Pause Full(如每分钟多次),可能存在内存泄漏或堆容量不敷。
2>. 观察内存回收效率
Eden 区回收:每次 Young GC 后 Eden 是否完全清空(如 Eden: 800M->0M 表示回收彻底)。
晋升到老年代的对象量:若每次 Young GC 后 Old 区大幅增长(如 Old: 256M->512M),可能存在过早晋升(检查新生代大小是否合理)。
3>. 辨认非常指标
长时间停顿:若 Real 时间凌驾 1 秒(如 Full GC 耗时 5 秒),需优化 GC 策略或堆大小。
频繁 Full GC:常见原因包括:
    老年代空间不敷(需增大 -XX:OldSize)。
    内存泄漏(对象无法回收,连续占用老年代)。

3、日记分析工具

3.1 GCViewer(离线分析工具)

实用场景:快速天生详细GC输出的可视化陈诉,适合本地或生产环境日记
下载地址:GCViewer
打开下令
java -jar gcviewer-1.37-SNAPSHOT.jar https://i-blog.csdnimg.cn/direct/72558a6bee1040738de993c48a345dc7.png
打开之后,点击File->Open File打开我们的GC日记,可以看到图
https://i-blog.csdnimg.cn/direct/405768f5405e43098b9187bd157f3c12.png
关键指标:
Throughput:应用运行时间占比(越高越好,一般需 >95%)。
Pause Time:总停顿时间和最大单次停顿。
Heap Size:堆内存使用趋势图。
详细的可以看下GitHub中的描述:https://github.com/chewiebug/GCViewer

3.2 GCEasy(在线分析工具)

实用场景:无需安装,快速天生详细陈诉。
访问:https://gceasy.io/
上传 gc.log 文件,自动天生分析陈诉
核心功能:
GC 原因统计(如 Allocation Failure、Metadata GC Threshold)。
内存泄漏检测:通过老年代增长趋势判断。
停顿时间分布:辨认长时间 GC 事件。
jvm堆:
https://i-blog.csdnimg.cn/direct/20d2600c5a504ff2a1d365f72a0bd1cb.png
Allocated:各部门分配大小
Peak:峰值内存使用量
关键绩效指标:
https://i-blog.csdnimg.cn/direct/fdab8d1639564029b6910ace12c88b76.png
吞吐量:93.769%,运行应用步伐的时间/(GC时间的比值+运行应用步伐的时间)
平均GC停顿时间
最大GC停顿时间
GC停顿连续时间范围:时间范围、GC数量、百分百
交互式图表:
https://i-blog.csdnimg.cn/direct/6631a5b1af0e4afda2bfb3d3ab219554.png
左边菜单有很多:
GC之前的堆、GC之后的堆、GC连续时间、GC停顿连续时间、回收的内存字节、Young区内存变革、Old区内存变
化、Metaspace内存变革、分配对象大小、对象从Young到Old内存大小变革

后序的内容有:GC统计信息、Minor GC/Full GC信息、内存泄漏、GC的原因等等
https://i-blog.csdnimg.cn/direct/3c44e5e273ac47f18062e40920327e09.png
https://i-blog.csdnimg.cn/direct/702516c9298f434f8622521e754c594d.png
https://i-blog.csdnimg.cn/direct/5042db76518241f69ae2bb2670459b5b.png

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: JVM监控