JVM 工具
jps
# -l 输出主类全名或 jar 路径 # -q 只输出 LVMID # -m 输出 JVM 启动时传递给 main() 的参数 # -v 输出 JVM 启动时显式指定的 JVM 参数 jps -lmv
jinfo
# 查看 jvm 参数 jinfo pid # 修改 jvm 参数(仅支持可修改的参数) # 启用GC日志 jinfo -flag +PrintGCDetails pid # 调整堆内存比例 jinfo -flag MaxHeapFreeRatio=40 pid
jstat
# 实时 GC 监控 jstat -gcutil pid 1000 5 # 每秒1次,共5次 # 堆内存分析(容量视图) # S0C/S1U : Survivor 区容量/使用量 # EU/CU : Eden 区使用量/容量 # OU/OC : 老年代使用量/容量 # MC/MU : Metaspace 容量/使用量 jstat -gc pid 2s # 每2秒刷新 # 类加载监控 jstat -class pid # JIT 编译监控 jstat -compiler pid # 查看最近 GC 原因 jstat -gccause pid
jstack
# 显示 native 方法栈 jstack -m pid > stack.log # 强制(适用于无响应进程)生成线程 dump jstack -F pid > force_dump.log # 显示锁的附加信息(同步器与资源锁) jstack -l pid > lock_info.log # 定位死锁 jstack pid | grep -A 10 deadlock # CPU 飙高分析 top -H -p pid # 获取高 CPU 线程 ID printf "0x%x\n" 12345 # 十进制转十六进制(得到 0x3039) jstack pid | grep -A 20 0x3039 # 线程状态统计: jstack pid | grep java.lang.Thread.State | sort | uniq -c # 连续抓取3次线程快照(间隔2秒) for i in {1..3}; do jstack pid >> thread_dumps.log; sleep 2; done # 结合时间戳记录 jstack pid | awk '{print strftime("%Y-%m-%d %H:%M:%S"), $0}' > timed_dump.log
jmap
# -dump 或 -histo:live 会触发 Full GC,生产环境谨慎使用 # Linux 可能需要 sudo 权限或与 Java 进程相同用户执行 # 查看堆内存分布(快速定位内存大户) jmap -histo pid | head -n 20 # 生成堆转储文件(用于 MAT 分析内存泄漏),format=b 表示生成的堆转储文件以二进制格式存储,这是唯一支持的格式 jmap -dump:live,format=b,file=./heapdump.hprof pid # 检查堆配置和 GC 算法 jmap -heap pid # 显示等待 Finalize 的对象队列 jmap -finalizerinfo pid # 显示类加载器统计信息 jmap -clstats pid
jhat
# 生成堆转储文件(需先获取Java进程PID) jmap -dump:format=b,file=heapdump.hprof pid # 使用jhat分析(默认端口7000) jhat -port 7000 heapdump.hprof jhat -J-Xmx256G -J-XX:+UseG1GC -J-XX:-UseGCOverheadLimit heapdump.hprof # 对于大 hprof 文件 # 浏览器打开 http://127.0.0.1:7000
jcmd
# 查看 JVM 所数
jcmd pid VM.flags
# 触发 GC
jcmd pid GC.run
# 触发 HeapDump
jcmd pid GC.heap_dump /var/log/jvm/manual_%p_%t.hprof
@echo off title HSDB set JAVA_HOME=D:\jdk8 set PATH=%PATH%;%JAVA_HOME%\bin @echo on start javaw -classpath %JAVA_HOME%/lib/sa-jdi.jar sun.jvm.hotspot.HSDB : java -classpath %JAVA_HOME%/lib/sa-jdi.jar sun.jvm.hotspot.CLHSDB : jdk9+ : start jhsdb hsdb : jhsdb clhsdb
start D:\jdk21.0.6\bin\jconsole.exe
visualvm & lanuage:https://github.com/zedoCN/VVM-Translator
cd /d D:\visualvm2110 set JAVA_HOME=D:\jdk21.0.6 set PATH=%PATH%;%JAVA_HOME%\bin rem https://visualvm.github.io/uc/release2110/updates.html start bin\visualvm.exe --userdir D:\visualvmdata\data --cachedir D:\visualvmdata\cache
cd /d D:\jmc9.0.0 set JAVA_HOME=D:\jdk21.0.6 set PATH=%PATH%;%JAVA_HOME%\bin start jmc.exe
Memory Analyzer Tool:https://eclipse.dev/mat
# 指定 JDK echo "-vm\\n/opt/jdk-21.0.6/bin" >> /opt/mat/MemoryAnalyzer.ini # GUI 启动 /opt/mat/MemoryAnalyzer -data ./workspace /opt/mat/MemoryAnalyzer -vm /opt/jdk-21.0.6/bin -vmargs -Xmx16g # 基础分析 /opt/mat/ParseHeapDump.sh /path/to/heapdump.hprof org.eclipse.mat.api:suspects -parse_threads 8 -output report.html # 参数配置 # 修改解析脚本内存配置(建议物理内存的 80%) sed -i 's/-Xmx4096m/-Xmx64g/' /opt/mat/ParseHeapDump.sh # 多线程解析(CPU 核数 × 2) export MAT_PARSER_THREADS=$(nproc) # 高级分析 # 内存泄漏追踪 ./ParseHeapDump.sh heapdump.hprof org.eclipse.mat.api:top_components -threshold 0.5 # 显示占用 0.5% 以上的对象 # 对象关系图谱生成 ./ParseHeapDump.sh heapdump.hprof org.eclipse.mat.api:overview -min_dominator 100MB # 过滤支配树 > 100 MB 的对象 # 超大堆文件处理(> 50GB): 分片解析技术 ./ParseHeapDump.sh heapdump.hprof org.eclipse.mat.api:suspects -keep_unreachable_objects -segment_size 4G
Unable to open socket file: target process not responding or HotSpot VM not loaded
常用参数
https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html & https://jvmmemory.com
运行时删掉注释和注意脚本文件换行符,日志目录需要手动新建,示例中为 /var/log/jvm。https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/felog.html & https://blog.csdn.net/u014454538/article/details/132526612
#!/bin/bash # cd /opt/app && mkdir -p logs/jvm JVM_OPTS=" # GC -XX:+PrintGC # 打印GC日志 -XX:+PrintGCDetails # 打印GC详细日志(退出前打印堆信息) -XX:+PrintGCDateStamps # 打印GC绝对系统时间 -XX:+PrintGCTimeStamps # 打印GC相对JVM启动时间 -XX:+PrintGCApplicationStoppedTime # 打印GC导致的STW时间 -XX:+PrintHeapAtGC # GC后打印堆数据(生产环境慎用) -XX:+PrintTenuringDistribution # 打印对象年龄分布 -XX:+PrintGCApplicationConcurrentTime # 打印程序执行时间 -XX:+PrintReferenceGC # 跟踪软/弱/虚引用和Finalize队列 -Xloggc:/var/log/jvm/gc_%t_%p.log # GC日志保存路径(时间戳防覆盖) -XX:+UseGCLogFileRotation # 开启日志轮转 -XX:NumberOfGCLogFiles=10 # 保留10个历史日志 -XX:GCLogFileSize=50M # 单个日志上限50MB # OOM -XX:+HeapDumpOnOutOfMemoryError # OOM 时自动生成堆转储 -XX:HeapDumpPath=/var/log/jvm/ # 转储文件路径,java_pidxxx.hprof -XX:OnOutOfMemoryError="mv /var/log/jvm/java_pid%p.hprof /var/log/jvm/java_pid%p_`date +%Y-%m-%d_%H:%M:%S`.hprof" # 发生 OOM 时执行命令 -XX:ErrorFile=/var/log/jvm/hs_err_%p.log # JVM 崩溃日志路径 -XX:OnError="mv /var/log/jvm/hs_err_%p.log /var/log/jvm/hs_err_%p_`date +%Y-%m-%d_%H:%M:%S`.log" # 发生 error 时执行命令 # Thread -XX:+UnlockDiagnosticVMOptions # 解锁诊断参数 -XX:+PrintSafepointStatistics # 打印安全点事件统计 -XX:PrintSafepointStatisticsCount=1 # 每次安全点都记录 -XX:-DisplayVMOutput # 禁用控制台输出 -XX:+LogVMOutput # 启用日志文件输出 -XX:LogFile=/var/log/jvm/vm.log # 安全点日志路径 " exec nohup java $JVM_OPTS -jar application.jar --spring.config.location=./ > /dev/null 2>&1 &
分析 gc.log:https://github.com/chewiebug/GCViewer
大内存下的 JVM 常用参数,例如 512G RAM:
# 基础配置 -Xmx410g -Xms410g # 建议堆内存占物理内存 80%(默认 JVM8 最大只会使用 32G,需显式配置) -XX:MaxMetaspaceSize=2g # 元空间,若是动态类加载场景还需更大 -XX:ReservedCodeCacheSize=1g # 代码缓存,对于 JIT 编译 # GC 优化(G1 策略) -XX:+UseG1GC -XX:InitiatingHeapOccupancyPercent=35 # 默认 45%,会让 G1 更早开始并发周期,适合内存充足的情况,但需要观察 GC 暂停时间是否在可接受范围内 -XX:G1HeapRegionSize=32m # G1 的 Region 大小通常根据堆大小自动计算,手动设置为 32MB 可能合适,因为堆很大,较大的 Region 可以减少内部碎片,但需要确认是否与自动计算的默认值冲突 -XX:ParallelGCThreads=N # 控制并行阶段(Young 区回收、混合回收)的线程数,容器环境最好显式设置(需匹配CGroup CPU配额) -XX:ConcGCThreads=N # 控制 G1/CMS 并发阶段(标记、清理)的线程数 -XX:+ExplicitGCInvokesConcurrent # 使 System.gc() 触发并发 GC 周期(非 STW Full GC) -XX:+UseStringDeduplication # 字符串去重(仅 G1) # 大内存优化 -XX:+AlwaysPreTouch # 在启动时预分配内存,避免运行时延迟,但会增加启动时间,避免内存分配抖动 -XX:+UseLargePages # 使用大内存页,可以减少页表开销,提升性能,但需系统配置好大页,否则可能导致启动失败 -XX:SurvivorRatio=10 # 调整 Eden 和 Survivor 区的比例,SurvivorRatio=10 意味着 Eden 是每个 Survivor 的 10 倍,这会影响年轻代的对象晋升速度,需结合应用的对象生命周期(年龄分布)来评估分析
打印所有 JVM 参数的默认值:java -XX:+PrintFlagsInitial -version
打印所有 JVM 参数在运行时的最终值(如果某个默认值被新值覆盖,则显示新值):java -XX:+PrintFlagsFinal -version
打印被用户或JVM修改过的参数:java -XX:+PrintCommandLineFlags -version
https://docs.oracle.com/javase/8/docs/technotes/tools
https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot

浙公网安备 33010602011771号