使用visualvm监控Java程序性能三——浏览堆dump文件
堆dump,即堆转储,其实是一个当前JVM堆内存所有对象在某个时间点上的快照。堆dump用来将当前应用程序的堆内存中的数据信息保存为文件,并可以快速浏览文件中的内容,查询对象分配信息。 在VisualVM中,堆dump的入口很多,可以再应用程序右键,选择堆dump;也可以打开主窗口的“监视”tab页,点击右上角有堆dump按钮;还可以打开抽样器tab页,进行内存抽样后,点击工具栏上的堆dump按钮。 1. 打开堆dump 执行完堆dump后,主窗口会打开一个堆dump的页面,同时应用程序节点会增加一个headdump+时间子节点,可以直接打开该节点来浏览堆dump文件信息,如图所示: 堆dump文件存储后缀为.hprof,除了能够看到本地堆dump文件,也可以通过菜单栏的文件-装入打开他人分享的dump文件: 2. 浏览堆dump文件信息 堆dump tab页包含了几个子标签页面:概要、类、实例、OQL控制台,我们重点说下前三个。 2.1. 概要 显示了转储堆dump时的信息,包括基本信息、环境信息、系统属性和线程信息,例如你可以看到堆dump时间、文件存放位置、大小等。 2.2. 类 类视图显示类的列表,以及该类引用的实例的数量和百分占比、类所有实例的大小和百分占比。您可以通过在实例视图中右键单击名称和选择“在实例图中显示”或者直接双击类来查看特定类的实例列表: 通过类视图,可以整体上明确哪些类实例数多,占用资源高。 可以通过最下方的“类目过滤器”来搜索类,点击漏斗形状的图标可以选择筛选类型,例如包含/不包含类名称、正则匹配、搜索子类等。例如,搜索类名包含EsSyncTask的所有类,如下图所示: 2.3. 实例数 当在类视图选择查询具体某一个类的实例时(右键或者双击),此时就打开了该类的实例视图。当您从实例窗格中选择一个实例时,VisualVM将显示该类的字段,并在各自的窗格中引用该类。 除了显示了具体的类和概要信息(实例数量、大小、总大小等)外,实例视图还有几个面板: 实例数:显示当前类的实例列表,点击具体的某一个实例可以在字段和引用面板查看实例的字段信息和引用了的对象 字段:显示当前选择的实例的具体字段,包括字段名称、类型、字段值等 引用:递归显示当前所有引用了该类的类实例,该面板会一层层递归显示引用,包括引用实例的再引用。通过引用面板,可以跟踪对象的引用情况,以便找到具体的类,从而优化代码。 通过右键点击实例或者在引用面板右键,可以查看最近垃圾回收根节点。 接下来,我们来编一个实例程序,看看堆dump的情况,代码如下: public class HeaddumpTest { public static void main(String[] args) { Refrence ref = new Refrence(); int id = 0; while (true) { ref.add(new MyClass(id++, "myclass" + id)); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } } } class Refrence { private List<MyClass> myClasses = new ArrayList<>(); public void add(MyClass myClass) { myClasses.add(myClass); } public List<MyClass> getMyClasses() { return myClasses; } public void setMyClasses(List<MyClass> myClasses) { this.myClasses = myClasses; } } class MyClass { private int id; private String name; MyClass(int id, String name) { this.id = id; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } ...