Mat工具使用
下载地址:https://www.eclipse.org/mat/downloads.php
Java的gc_roots结构
System Class:系统类,启动类加载的一些类,在运行期间肯定会使用到的,它们能够作为GC root对象。都是一些class的实例对象。
JNI Global(老师讲课是Nactive Stack,按老师的来):JVM虚拟机在执行一些本地方法调用时必须调用操作系统方法,操作系统方法执行时所引用的一些java对象,其也可以作为根对象。
Thread:指的是一些活动线程,活动线程中使用的一些对象不能够被当成垃圾。线程在一次次运行时会有方法进行调用,那么也会产生一个栈帧,栈帧内所引用的对象可以作为根对象,局部变量引用的对象都可以作为一个根对象。
Busy Monitor:java对象中具有同步锁机制,也就是synchronized关键字,若是使用某个对象作为锁,那么该对象自然也不会被当成垃圾被回收。加锁的对象。
实际小案例
1、查看主线程方法中某个根节点的存在
案例描述:在程序中我们通过进行一次强引用以及取消引用来构建快照,并使用Mat工具来进行监测根对象的存在。
import java.io.*; import java.util.ArrayList; import java.util.List; /** * 演示GC Roots */ public class Main { public static void main(String[] args) throws InterruptedException, IOException { //list1是一个变量,存储在活动栈帧里,相应的对象存储在堆中 List<Object> list1 = new ArrayList<>(); list1.add("a"); list1.add("b"); System.out.println(1); System.in.read();//阶段1:构建快照 list1 = null;//取消强引用 System.out.println(2); System.in.read(); System.out.println("end...");//阶段2:构建快照 } }
分别在输出1、2时创建快照,我们可以借助jmap来进行创建
# 获取当前运行程序的进程号 jps # 创建两次快照 jmap -dump:format=b,live,file=1.bin 10556 # -dump表示将当前堆内存的状态抓取转储成一个文件,format=b表示二进制,live指的是抓快照时只抓取存活的对象,垃圾回收掉的会进行过滤,注意设置live参数会主动触发一次垃圾回收。 jmap -dump:format=b,live,file=2.bin 10556
此时我们就会在指定目录得到两个.bin文件,接着来使用Mat工具来进行分析:
查看GC roots对象
快照1:
快照2:由于jmap设置了live参数,所以在生成快照前进行了GC垃圾回收,并且由于已经对该集合对象设置了null,则表示不再进行强引用,那么此时垃圾回收就会将其清理掉了,自然下面也就查看不到了!