1、可达性分析算法
可达性分析算法(Reachability Analysis)的基本思路是,通过一些被称为引用链(GC Roots)的对象作为起点,从这些节点开始向下搜索,搜索走过的路径被称为Reference Chain,当一个对象到GC Roots没有任何引用链相连时(即从GC Roots节点到该节点不可达),则证明该对象是不可用的。如下图:
通过可达性算法,成功解决了引用计数所无法解决的问题"循环依赖",只要你无法与GC Root建立直接或间接的连接,系统就会判定为可回收对象,那这样就引申出了另一个问题,哪些输入GC Root
2、Java内存区域
在Java语言中,可作为GC Root的对象包括以下4种:
- 虚拟机栈(栈帧中的本地变量表)中引用的对象
- 方法区中类静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中JNI(即一般说的Native方法)引用的对象
1) 虚拟机栈(栈帧中的本地变量表)中引用的对象
此时的s,即为GC Root,当s置为空时,StackLocalParameter对象也断掉了与GC Root的引用链,将被回收。
public class ReachabilityAnalysisGC {
public static void main(String[] args){
testGC();
}
public static void testGC(){
StackLocalParameter s = new StackLocalParameter("StackLocalParameter");
s = null;
}
}
class StackLocalParameter {
public StackLocalParameter(String name){}
}
2) 方法区中类静态属性引用的对象
s为GC Root,s置为null,经过GC后,s所指向的properties对象由于无法与GC Root建立关系被回收
而m作为类的静态属性,也属于GC Root,parameter 对象依然与 GC root 建立着连接,所以此时 parameter 对象并不会被回收。
public class ReachabilityAnalysisGC {
public static void main(String[] args){
testGC();
}
public static void testGC(){
MethodAreaStaicProperties s = new MethodAreaStaicProperties("properties");
s.m = new MethodAreaStaicProperties("parameter");
s = null;
}
}
class MethodAreaStaicProperties {
public static MethodAreaStaicProperties m;
public MethodAreaStaicProperties (String name){}
}
3) 方法区中常量引用的对象
m即为方法区中的常量引用的对象,也为GC Root,s置为null后,final对象也不会因没有与GC Root建立联系而被回收
public class ReachabilityAnalysisGC {
public static void main(String[] args){
testGC();
}
public static void testGC(){
MethodAreaStaicProperties s = new MethodAreaStaicProperties("staticProperties");
s = null;
}
}
class MethodAreaStaicProperties {
public static final MethodAreaStaicProperties m =new MethodAreaStaicProperties("final");
public MethodAreaStaicProperties(String name){}
}
4) 本地方法栈中引用的对象
任何Native接口都会使用某种本地方法栈,实现的本地方法接口是使用C连接模型的话,那么它的本地方法栈就是C栈。当线程调用Java方法时,虚拟机会创建一个新的栈帧并压入Java栈。然而当它调用的是本地方法时,虚拟机会保持Java栈不变,不再在线程的Java栈中压入新的帧,虚拟机只是简单地动态连接并直接调用指定的本地方法。
参考出处:阿里巴巴中间件微信公众号
你的鼓励是我分享技术最大的动力!如有错误之处,请指正,不胜感激。