首先编写一段测试代码
package com.tech.gc.root;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* @author lw
* @since 2021/11/3
*/
public class Demo_1 {
public static void main(String[] args) throws IOException {
List<Object> list=new ArrayList<>();
list.add("a");
list.add("b");
System.out.println(1);
System.in.read();
list=null;
System.out.println(2);
System.in.read();
System.out.println("end...");
}
}
当程序打印1后,使用jmap dump出内存快照
# jps 查看进程ID
# b:二进制文件,live存活对象(会主动触发一次gc),file 指定文件名称
jmap -dump:format=b,live,file=1.bin 进程ID
当程序打印2后,再次使用jmap 抓取一次内存快照
jmap -dump:format=b,live,file=2.bin 进程ID
打开mat工具,并导入2个内存快照文件:
查看1.bin的内存快照的GC Roots
gc roots有四类:系统类、本地方法栈、线程、监视器类
打开线程类,打开main线程
可以看到栈帧的本地变量有我们创建的ArrayList对象,ArrayList就是一个根对象。
在查看2.bin内存快照的GC Roots
发现已经没有ArrayList对象了,这是因为在代码中list=null,ArrayList不再是根对象,ArrayList对象没有引用,在GC时被回收。
因此可以使用MAT工具分析哪些对象可以作为GC ROOTS。
GCROOTS对象,包括一些系统对象及用户程序使用的对象,用户程序使用的对象包括:
1 栈帧中本地变量引用的对象
2 本地方法栈中引用的对象
3 方法区静态变量引用的对象
4 方法区常量引用的对象