其他分享
首页 > 其他分享> > 第三章:JVM判定哪些对象可回收

第三章:JVM判定哪些对象可回收

作者:互联网

 

①引用计数算法

原理:给对象添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;在任何时刻计数器的值为0的对象就是不可能再被使用的,也就是可被回收的对象。

它有一个致命的缺陷,那就是它无法解决对象之间相互循环引用的的问题,对于循环引用的对象它无法进行回收。

public class Object {

public Object instance;

public static void main(String[] args) {

// 1
Object objectA = new Object();
Object objectB = new Object();

// 2
objectA.instance = objectB;
objectB.instance = objectA;

// 3
objectA = null;
objectB = null;

}
}

 

 

程序启动后,objectA和objectB两个对象被创建并在堆中分配内存,这两个对象都相互持有对方的引用,除此之外,这两个对象再无任何其他引用,实际上这两个对象已经不可能再被访问(引用被置空,无法访问),但是它们因为相互引用着对方,导致它们的引用计数器都不为0,于是引用计数算法无法通知GC收集器回收它们。

实际上,当第1步执行时,两个对象的引用计数器值都为1;当第2步执行时,两个对象的引用计数器都为2;当第3步执行时,二者都清为空值,引用计数器值都变为1。根据引用计数算法的思想,值不为0的对象被认为是存活的,不会被回收;而事实上这两个对象已经不可能再被访问了,应该被回收。

 

 

②可达性分析算法

主流的JVM中,都是通过可达性分析算法来判定对象是否存活的。

可达性分析算法的基本思想是:通过一系列被称为"GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索走过的路径称为引用链,当一个对象到GC Roots对象没有任何引用链相连,就认为GC Roots到这个对象是不可达的,判定此对象为不可用对象,可以被回收。

 

在上图中1234可达的,不会被回收;567它们将会被判定为是可回收的对象。

 

在Java中,可作为GC Roots的对象包括下面几种:

1、虚拟机栈中引用的对象;

2、方法区中类静态属性引用的对象;

3、方法区中常量引用的对象;

4、本地方法栈中Native方法引用的对象。

 

③GC Roots对象 在 Java 语言中,可作为 GC Root 的对象包括以下4种:

 

★ 虚拟机栈(栈帧中的本地变量表)中引用的对象此时的 s,即为 GC Root,当s置空时,localParameter 对象也断掉了与 GC Root 的引用链,将被回收。

public class StackLocalParameter {

   public StackLocalParameter(String name){}

}

public static void testGC(){

   StackLocalParameter s = new StackLocalParameter("localParameter");

   s = null;

}

★ 方法区中类静态属性引用的对象
s 为 GC Root,s 置为 null,经过 GC 后,s 所指向的 properties 对象由于无法与 GC Root 建立关系被回收。而 m 作为类的静态属性,也属于 GC Root,parameter 对象依然与 GC root 建立着连接,所以此时 parameter 对象并不会被回收。

public class MethodAreaStaicProperties {

   public static MethodAreaStaicProperties m;

   public MethodAreaStaicProperties(String name){}

}

public static void testGC(){

   MethodAreaStaicProperties s = new MethodAreaStaicProperties("properties");

   s.m = new MethodAreaStaicProperties("parameter");

   s = null;

}

★ 方法区中常量引用的对象m 即为方法区中的常量引用,也为 GC Root,s 置为 null 后,final 对象也不会因没有与 GC Root 建立联系而被回收。

public class MethodAreaStaicProperties {

   public static final MethodAreaStaicProperties m = MethodAreaStaicProperties("final");

   public MethodAreaStaicProperties(String name){}

}

public static void testGC(){

   MethodAreaStaicProperties s = new MethodAreaStaicProperties("staticProperties");

   s = null;

}

★  本地方法栈中引用的对象
任何 Native 接口都会使用某种本地方法栈,实现的本地方法接口是使用 C 连接模型的话,那么它的本地方法栈就是 C 栈。当线程调用 Java 方法时,虚拟机会创建一个新的栈帧并压入 Java 栈。然而当它调用的是本地方法时,虚拟机会保持 Java 栈不变,不再在线程的 Java 栈中压入新的帧,虚拟机只是简单地动态连接并直接调用指定的本地方法。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

标签:第三章,对象,可回收,MethodAreaStaicProperties,GC,引用,JVM,Root,public
来源: https://www.cnblogs.com/Lucky-stars/p/11637838.html