对象存活的判断
引用计数法(Reference Counting)
在对象中添加一个引用计数器,每当有一个地方引用它时,计数器值加一;
引用失效时,计数器值减一;计数器值为零的对象表示不再使用。
此方式有循环引用的问题,即
A
引用B
、B
引用A
,不做处理,最终A
与B
均无法回收。主流的
Java
虚拟机没有使用此方式。
Netty中的引用计数法
ByteBuf byteBuf = ctx.alloc().directBuffer(); // netty中分配直接内存
System.out.println(byteBuf.refCnt()); // 初始化引用计数值为1
byteBuf.retain(); // CAS 引用计数加1
byteBuf.release(); // CAS 引用计数减1
可达性分析算法(Reachability Analysis)
通过一些列GC Roots
的根对象作为起点,搜索其引用的对象,
搜索时经过的路径称为引用链(Reference Chain
),
如果对象不在任何引用链中,则表示不再使用。
可作为GC Roots的对象
在虚拟机栈(栈桢中的本地变量表)中引用的对象
正在执行的方法所引用的对象自然是存活的
在方法区中类静态属性引用的对象
除非类型卸载,否则静态属性引用的对象也应该是存活的
在方法区中常量引用的对象(字符串常量池里的引用)
- 在本地方法栈中
JNI
(就是Native
方法)引用的对象 Java
虚拟机内部的引用,如基本数据类型对应的Class
对象、常驻的异常对象、类加载器等- 所有被同步锁持有的对象
- 反映
Java
虚拟机内部情况的JMXBean
、JVMTI
中注册的回调、本地代码缓存等。