可达性算法分析
原理:找出所有的GC Roots根,根据GC Roots根引用的对象向下找去,所走过的路径成为引用链,当一个对象没有GC Roots根相连接,则为不可达,就是无效的垃圾对象。
Gc Roots根结点:线程栈的本地变量,方法区中类静态属性引用的对象,方法区中常量引用的对象,本地方法栈的变量。
引用计数算法
原理:给对象添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减一;任何时刻计数器为0的对象就是不可能再被使用的。
优点:实现简单,判断效率高
缺点:很难解决对象间相互循环引用的问题
public class ReferenceCountingGC {
public Object instance=null;
private static final int _1MB=1024*1024;
private byte[]bigSize=new byte[2*_1MB];
public static void testGC(){
ReferenceCountingGC objA=new ReferenceCountingGC();
ReferenceCountingGC objB=new ReferenceCountingGC();
objA.instance=objB;
objB.instance=objA;
objA=null;
objB=null;
System.gc();
}
}
上述代码中objA和objB这两个对象,除了互相引用,再也没有其他的任何引用,理论上这两个对象已经不可能再被访问,但是他们因为互相吸引着对方,导致他们的引用计数都不为0,这种情况下采用计数算法就没有办法通知GC收集器回收他们。
引用
通过上面两个算法,我们可以发现,想要判断一个对象是否已死,本质上判断的就是对象是否会再被引用JDK1.2以前,Java中的关于引用的定义便只有被引用或者没有被引用两种状态,就会导致一些对象占用内存。于是出现了以下四种引用(引用强度逐渐减弱)的定义:
强引用
例:Object obj=new Object(); 这类引用都被称为强引用,只要强引用还在,垃圾收集器永远不会回收掉被引用的对象。
软引用
用来描述一些还有用但是并非必需的对象。软引用的对象在系统内将要发生内存溢出之前,将会把这些对象列进回收范围之中进行第二次回收,如果核磁回收内存还是不够,才会抛出内存溢出异常。JDK1.2后提供了SoftReference类来实现软引用。
弱引用
用来描述非必需对象,强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次垃圾收集发生之前。当垃圾收集器工作时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。
JDK1.2后提供了WeakReference类来实现弱引用。
虚引用
虚引用也成为幽灵引用或者幻影引用,它是最弱的一种引用关系。一个对象是否有虚引用的存在。完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。
JDK1.2之后提供了PhantomReference类来实现虚引用。