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

HSDB

@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

jconsole

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

jmc(JDK Mission Control)

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.htmlhttps://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

posted @ 2019-05-27 15:23  江湖小小白  阅读(1274)  评论(0)    收藏  举报