VisualVM是到目前为止随JDK发布的功能最强大的运行监视和故障处理程序,并且可以预见在未来一段时间内都是官方主力发展的虚拟机故障处理工具。他除了运行监视,故障处理外,还提供了很多其他方面的功能。如性能分析等
VisualVM基于NetBeans平台开发,因此它一开始就具备了插件扩展功能的特性,通过插件扩展支持,VisualVM可以做到:
Visualvm.exe 可以在JDK安装路径bin目录找到,运行即可监视本地Java程序
使用IDEA的同学可以安装VisualVM插件使用更方便.
安装完就能看到运行处多了两个图标,点击就能启动VisualVM
在演示之前我们先准备一段测试程序,后面用Visualvm对这段程序运行情况分析
public class TestJvm {
public static void main(String[] args) {
byte[] allocation1, allocation2, allocation3, allocation4, allocation5;
//为了方便监视,这里休眠一下
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
allocation1 = new byte[4*1024*1024];
allocation2 = new byte[1*1024*1024];
allocation3 = new byte[4*1024*1024];
allocation4 = new byte[4*1024*1024];
allocation4= null;
allocation5 = new byte[4*1024*1024];
}
}
程序运行时参数设置
-XX:+PrintGCDetails 打印GC日志
-Xms20M 初始堆大小
-Xmx20M 最大堆大小
-Xmn10M 新生代堆大小
运行观察日志打印
[GC (Allocation Failure) [PSYoungGen: 8192K->1016K(9216K)] 8192K->1632K(19456K), 0.0040618 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 8342K->1016K(9216K)] 13054K->6684K(19456K), 0.0030396 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Ergonomics) [PSYoungGen: 6244K->5086K(9216K)] [ParOldGen: 9764K->6542K(10240K)] 16009K->11628K(19456K), [Metaspace: 9157K->9157K(1058816K)], 0.0413284 secs] [Times: user=0.20 sys=0.00, real=0.04 secs]
[GC (Allocation Failure) [PSYoungGen: 8192K->984K(9216K)] 14734K->7526K(19456K), 0.0021684 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
PSYoungGen total 9216K, used 1220K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
eden space 8192K, 2% used [0x00000000ff600000,0x00000000ff63b068,0x00000000ffe00000)
from space 1024K, 96% used [0x00000000ffe00000,0x00000000ffef6010,0x00000000fff00000)
to space 1024K, 0% used [0x00000000fff00000,0x00000000fff00000,0x0000000100000000)
ParOldGen total 10240K, used 6542K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
object space 10240K, 63% used [0x00000000fec00000,0x00000000ff263838,0x00000000ff600000)
Metaspace used 9172K, capacity 9514K, committed 9728K, reserved 1058816K
class space used 1090K, capacity 1186K, committed 1280K, reserved 1048576K
控制台能够观察到我们这里发生3次GC和1次Full GC
在监视窗口下,可以看到CPU、堆、线程等使用情况实时监控
在Visual GC窗口下,可以看到年轻代和老年代的GC次数和时间使用情况
在抽样器点击内存抽样,可以快照实时的内存使用情况,包括实例和字节数,发生内存溢出时,可以通过字节使用情况定位原因
VisualVM 还可以分析堆dump文件
上面的程序我们修改下,让其发生内存溢出,然后dump堆文件
增加参数
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=java.hprof 发生内存溢出时dump堆使用情况
public class TestJvm {
public static void main(String[] args) {
byte[] allocation1, allocation2, allocation3, allocation4, allocation5;
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
allocation1 = new byte[4*1024*1024];
allocation2 = new byte[1*1024*1024];
allocation3 = new byte[4*1024*1024];
allocation4 = new byte[4*1024*1024];
// try {
// Thread.sleep(10000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
allocation5 = new byte[3*1024*1024];
}
}
发生内存溢出后,可以在项目的根目录找到我们dump的java.hprof文件
在VisualVM 文件–》装入–》选择堆dump 将java.hprof加载到Visual VM中
在概述窗口可以查看内存溢出的位置
在类窗口可以看出发生内存溢出时,堆的使用情况
通过上面两个窗口的内容分析,基本能够定位出内存溢出的原因,方便我们调整
我们上面讲的都是VisualVM监控本地的java进程,更多的场景是我们监视服务器的使用情况,我们可以通过VisualVM远程连接服务器达到监视的目的。
想要监视服务器情况,需要在服务器运行jstatd 守护进程
grant codebase "file:${java.home}/../lib/tools.jar" {
permission java.security.AllPermission;
};
连接成功将就可以监视服务器的运行状况了
参考资料:《深入理解Java虚拟机》