VisualVM 是一款免费的\集成了多个JDK 命令行工具的可视化工具,它能为您提供强大的分析能力,对 Java 应用程序做性能分析和调优。这些功能包括生成和分析海量数据、跟踪内存泄漏、监控垃圾回收器、执行内存和 CPU 分析,同时它还支持在 MBeans 上进行浏览和操作。
在内存分析上,Java VisualVM的最大好处是可通过安装Visual GC插件来分析 GC(Gabage Collection)趋势、内存消耗详细状况。
Java VisualVM默认没有安装Visual GC插件,需要手动安装,JDK的安装目录的bin目露下双击jvisualvm.exe,即可打开Java VisualVM,点击菜单栏 工具->插件 安装Visual GC
安装完成后重启Java VisualVM,Visual GC界面自动打开,即可看到JVM中堆内存的分代情况:
被监控的程序运行一段时间后Visual GC显示如下:
要看懂上面的图必须理解Java虚拟机的一些基本概念:
堆(Heap) :JVM管理的内存叫堆
分代:根据对象的生命周期长短,把堆分为3个代:Young,Old 和 Permanent,根据不同代的特点采用不同的收集算法,扬长避短也。
Young(年轻代)年轻代分三个区。一个 Eden 区,两个Survivor 区。大部分对象在 Eden 区中生成。当 Eden 区满时,还存活的对象将被复制到 Survivor 区(两个中的一个),当这个 Survivor 区满时,此区的存活对象将被复制到另外一个 Survivor 区,当这个 Survivor 去也满了的时候,从第一个 Survivor 区复制过来的并且此时还存活的对象,将被复制到 “年老区(Old)” 。需要注意,Survivor 的两个区是对称的,没先后关系,所以同一个区中可能同时存在从 Eden 复制过来对象,和从前一个 Survivor 复制过来的对象,而复制到年老区的只有从第一个 Survivor 复制过来的对象。而且,Survivor 区总有一个是空的。Old(年老代)年老代存放从年轻代存活的对象。一般来说年老代存放的都是生命期较长的对象。如果 Old 区也满了,将会触发 Full GC ,回收整个堆内存。Perm(持久代)用于存放的主要是类的 Class 对象。持久代对垃圾回收没有显著影响,但是有些应用可能动态生成或者调用一些 class,例如 Hibernate 等,在这种时候需要设置一个比较大的持久代空间来存放这些运行过程中新增的类。持久代大小通过 -XX:MaxPermSize= 进行设置。如果一个类被频繁的加载,也可能会导致 Perm 区满,Perm 区的垃圾回收也是由 Full GC 触发的。GC的基本概念
gc 分为 full gc 和 minor gc,当每一块区满的时候都会引发 gc。
Scavenge GC一般情况下,当新对象生成,并且在 Eden 申请空间失败时,就触发了 Scavenge GC,堆 Eden 区域进行 GC,清除非存活对象,并且把尚且存活的对象移动到 Survivor 区。然后整理 Survivor 的两个区。
Full GC对整个堆进行整理,包括 Young、Tenured 和 Perm。Full GC 比 Scavenge GC 要慢,因此应该尽可能减少 Full GC。有如下原因可能导致 Full GC:
上一次 GC 之后 Heap 的各域分配策略动态变化
System.gc() 被显示调用Perm 域被写满Old 被写满内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。
内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。其实说白了就是该内存空间使用完毕之后未回收。
1.监视界面(cpu,类,堆,线程)
2.线程界面
3.抽样器界面(性能剖析)
点击 CPU 按钮执行 cpu 分析查看方法
点击内存按钮执行内存分析查看类
4.堆dump和线程dump操作
Dump文件是进程的内存镜像,可以把程序的执行状态通过调试器保存到dump文件中。
堆dump的dump文件内容如下图所示:
线程dump的dump文件内容如下图所示:
如果还有什么不清楚的地方,可以参考文章 《使用 VisualVM 进行性能分析及调优》 。