Java虚拟机(七)虚拟机性能监控、故障处理工具

基础故障工具

在JDK中,有很多工具可以进行对虚拟机的性能监控,或者是故障处理。

jps:虚拟机进程状况工具

之前在讲多线程的时候也有用到了,在检查死锁问题的时候,使用jps查看是哪个线程。

jps

jstat:虚拟机统计信息工具

jstat可以用于对线程的监控和统计,如图:

对 15192线程查询GC的情况,一共查询20次,每250ms一次。

jinfo:Java配置工具

jinfo可以用于查询和配置Java虚拟机的配置信息,但在Windows平台限制较大,只能使用-flag指令。

jmap:Java内存映像工具

能进行对内存的信息进行快照存储,如图:

让虚拟机生成堆转储快照文件,一个生成的文件名为eclipse.bin ,去进程15192获取。

jhat:虚拟机堆转储快照分析工具

jhat命令可以和jmap搭配使用。如图:

能够分析出这个eclipse文件,看到分析结果。

jstack:Java堆栈跟踪工具

能够追踪到Java堆栈的运行状况,如图:

拿出之前发生过死锁的程序来进行判断,寻找死锁的原因。

可视化故障工具

JDK除了大量的命令行工具之外,也有一些好用的可视化工具去对故障进行处理。

JHSDB:基于服务性代理的调试工具

JHSDB是一款基于服务性代理实现的进程外调试工具。它可以在一个独立的JAVA虚拟机进程里分析其他的HotSpot虚拟机的内部数据。我们这次就是JHSDB分析一下以下代码,看看staticObj、instanceObj、localObj存放在哪里?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* staticObj、instanceObj、localObj存放在哪里?
*/
//-Xmx10m -XX:+UseSerialGC -XX:-UseCompressedOops
public class test {

static class Test {
static ObjectHolder staticObj = new ObjectHolder();
ObjectHolder instanceObj = new ObjectHolder();

void foo() {
ObjectHolder localObj = new ObjectHolder();
System.out.println("done"); // 这里设一个断点
}
}

private static class ObjectHolder {}

public static void main(String[] args) {
Test test = new Test();
test.foo();
}
}

首先通过jps查询进程,再通过Jhsdb打开图形化模式。

打开后如图:

运行到断点处,一共会创建三个ObjectHolder对象的实例。只要是对象实例,就必然会在Java堆中分配。

先点击菜单的Tools-> Heap Parameters

接着在Windows的

scanoops 0x0000020717600000 0x0000020717950000 test$ObjectHolder

注意要使用相应的内存地址,在寻找的时候你也可以看到cmd同时也进行的寻址:

最后我们运行完,可以看到这三行内容:

找出了这三个实例的地址。然后继续使用tools的Inspector,去查找:

发现查找到的正是我们所在的类的内存,接下来要根据堆中对象实例地址找出引用它们的指针。使用如下命令:

那么在根据得到的指针去寻找是否就是对应的对象。

可以看到,正是指向了我们所引用的对象实例,可见这是正确的行为。接下来试试第二个:

再查找:

第三个:

发现第三个居然不行了,直接显示为null,表示查找不到这个指针。看来revptrs命令并不支持查找栈上的指针,但这并不妨碍我们。我们还可以用Java Thread窗口的main线程,点击Stack Memory,手动去寻找栈内存。

如此一来,三个对象都找到了,还追溯到了引用它们的地方。