文章目录
1. JHSDB
基于服务性代理(HotSpot VM 中一组用于映射 Java VM 运行信息的 API 集合,可以通过独立的 Java VM 进程分析其他 HotSpot VM 的内部数据)的进程外调试工具,类似 JCMD 的多功能工具箱;
- JHSDB vs. JCMD
基础工具 | JCMD | JHSDB |
---|---|---|
jps -lm | jcmd | N/A |
jmap -dump pid | jcmd pid GC.heap_dump | jhsdb jmap --binaryheap |
map -histo pid | jcmd pid GC.class_histogram | jhsdb jmap --histo |
jstack pid | jcmd pid Thread.print | jhsdb jstack --locks |
jinfo -sysprops pid | jcmd pid VM.system_properties | jhsdb info --sysprops |
jinfo -flags pid | jcmd pid VM.flags | jhsdb jinfo --flags |
- 通过 JHSDB 查看变量本身位置
VM Arguments 设置
# 限制 Java Heap 大小,加快在内存中搜索对象
# 禁用压缩指针(JHSDB 对压缩指针的支持存在缺陷)
-Xmx10m -XX:+UseSerialGC -XX:-UseCompressedOops
示例代码
static class ObjectHolder {
}
static class Test {
// 随类信息存放在方法区
static ObjectHolder staticObj = new ObjectHolder();
// 随对象存放在 Java Heap
ObjectHolder instanceObj = new ObjectHolder();
void foo() {
// 存放在 foo() 方法栈帧的局部变量表
ObjectHolder localObj = new ObjectHolder();
System.out.println("done.");
}
}
public static void main(String[] args) {
Test test = new JHSDBTest.Test();
test.foo();
}
JHSDB 使用
# 找到要分析的程序的进程号
jps -l
# 进入 JHSDB 图形化界面,附加进程 20
jhsdb hsdb --pid 20
Tools -> Heap Parameters
: 查看内存布局;Windows -> Console
: 可以通过 scanoops 命令查找 Java Heap 中的对象实例,eg:hsdb>scanoops 0x00007f32c7800000 0x00007f32c7b50000 JHSDB_TestCase$ObjectHolder
;Tools -> Inspector
: 通过地址查找对象本身,展示对象头和对象元数据(Java 类型名称、继承关系、实现接口关系、字段信息、方法信息、运行时常量池的指针、内嵌的虚方法表、接口方法表等);Stack Memory
: 查看现场的栈内存;
2. JConsole(Java Monitoring and Management Console)
基于 JMX(Java Management Extensions)的可视化监视、管理工具;通过 JMX 的 MBean(Managed Bean)对系统进行信息收集和参数动态调整;
概述
,堆内存使用情况、线程、类、CPU 使用情况的概览;内存
,相当于可视化的 jstat,堆 Java Heap 的状态和 GC 信息做持续采集展示;线程
,相当于可视化的 jstack,分析线程停顿问题(外部资源等待、死循环、锁等);类
,Loaded Class 统计信息;VM 摘要
,JVM 进程配置与环境等摘要信息;MBean
,实现了 JMX 接口的 Managed Bean 对象;
3. VisualVM
All-in-One Java Troubleshooting Tool,功能最强大的运行监视和故障处理工具之一,比值专业收费的 Profiling 工具(JProfiler、YourKit)也不遑多让;不需要基于特殊 Agent,且对应用程序性能影响较小,可在生产环境直接使用;
- 配置 VisualVM 的 JAVA_HOME
# 在 VisualVM/Contents/Resources/etc/visualvm.conf 追加 jdk home
visualvm_jdkhome="/Users/cm.huang/Documents/devutils/jdk8u345-b01//Contents/Home"
- VisualVM 功能(配合插件)
- 显示 JVM 进程及配置、环境信息(jps、jinfo -> Overview);
- 监视 JVM 进程的 CPU、GC、Heap、Method Area、Thread 等信息(jstat、jstack -> Monitor);
- 生成和分析 Heap、Thread 转储快照(jmap、jhat、jstack -> Monitor、Threads);
- 跟踪方法级运行性能,分析调用最多、耗时最久的方法(Profiler);
- BTrace 动态日志跟踪
BTrace
,基于 Java 虚拟机的 Instrument 开发的,可实现动态修改目标程序的工具;可用于打印堆栈、参数、返回值等,进而进行性能监视、定位连接泄漏、内存泄漏、分析多线程竞争问题等;
代码示例
// 目标程序代码
public class BTraceTest {
public int add(int a, int b) {
return a + b;
}
public static void main(String[] args) throws IOException {
BTraceTest test = new BTraceTest();
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
for (int i = 0; i < 10; i++) {
reader.readLine();
int a = (int) Math.round(Math.random() * 1000);
int b = (int) Math.round(Math.random() * 1000);
System.out.println(test.add(a, b));
}
}
}
// BTrace 织入的代码
/* BTrace Script Template */
import org.openjdk.btrace.core.annotations.*;
import static org.openjdk.btrace.core.BTraceUtils.*;
@BTrace
public class TracingScript {
@OnMethod(clazz = "edu.aurelius.jvm.util.BTraceTest", method = "add", location = @Location(Kind.RETURN))
public static void func(@Self edu.aurelius.jvm.util.BTraceTest instance, int a, int b, @Return int result) {
println("调用堆栈:");
jstack();
println(strcat("方法参数A:", str(a)));
println(strcat("方法参数B:", str(b)));
println(strcat("方法结果:", str(result)));
}
}
运行结果
在 BTrace 织入上文代码,点击 Start,然后在目标程序控制台输入回车触发程序循环执行,观察 BTrace 的 Output 面板输出;
* Starting BTrace task
** Compiling the BTrace script ...
*** Compiled
** Instrumenting 1 classes ...
*** Done
** BTrace up&running
*** Done
** BTrace up&running
调用堆栈:
edu.aurelius.jvm.util.BTraceTest.add(BTraceTest.java:13)
edu.aurelius.jvm.util.BTraceTest.main(BTraceTest.java:23)
方法参数A:969
方法参数B:328
方法结果:1297
调用堆栈:
edu.aurelius.jvm.util.BTraceTest.add(BTraceTest.java:13)
edu.aurelius.jvm.util.BTraceTest.main(BTraceTest.java:23)
方法参数A:528
方法参数B:802
4. JMC(Java Mission Control)
JFR(Java Flight Recorder,对生产环境影响很低的 JVM 内建监控和信息收集框架,对目标应用完全透明)飞行记录仪用于持续收集数据,JMC 用于监控 JVM 的 MBean,作为 JMX 的控制台,也作为 JFR 的分析工具;
VM Arguments 设置
-Dcom.sun.management.jmxremote.port=9999 # jmx 服务端口
-Dcom.sun.management.jmxremote.ssl=false # 启用 ssl 连接
-Dcom.sun.management.jmxremote.authenticate=false # 启用授权校验
-Djava.rmi.server.hostname=localhost # jmx 服务主机名
-XX:+UnlockCommercialFeatures # 启用商业特性
-XX:+FlightRecorder # 启用 JFR
飞行记录器信息
一般信息
,JVM、操作系统相关信息;内存
,Memory 和 GC 相关信息;代码
,Mehtod、Exception、Compiler、Class Loader 等信息;线程
,Threads、Lock 等;I/O
,File、Socket 等的 Input/Output 信息;系统
,JVM 的运行环境(系统、进程、环境变量等);事件
,事件类型的信息;
JFR 提供的数据往往比其他工具通过代理或 MBean 获取的质量要高得多;
GC
,分代大小、GC 次数、时间、占用率等;内存
,一段时间分配了哪些对象、哪些在 TLAB 分配、分配速率、压力大小、分配的线程、GC 对象分代晋升情况等;
5. MAT(Memory Analyzer Tool)(WIP)
6. JProfiler(WIP)
7. Arthas(WIP)
# download
curl -O https://arthas.aliyun.com/arthas-boot.jar
# attach
java -jar arthas-boot.jar <pid>
8. Frame Graphs(WIP)
上一篇:「JVM 故障诊断」命令行工具
下一篇:「JVM 故障诊断」HotSpot VM 插件与工具
PS:感谢每一位志同道合者的阅读,欢迎关注、评论、赞!
参考资料:
- [1]《深入理解 Java 虚拟机》