堆中几乎存放这Java世界中所有的对象实例,垃圾收集器在对堆进行回收前,第一件事情就是要确定这些对象有哪些还"存活"着,哪些已经"死去"(即不可能再被任何途径使用的对象)。
1,引用计数算法
给对象添加一个引用计数器,每当有一个地方引用它时,计数器就加1;当引用失效时,计数器就减1;任何时刻计数器都为0的对象就是不可能再被使用的。客观地讲,引用计数法的实现简单,判定效率也高,但Java中没有选用其来管理内存,其中最主要的原因是它很难解决对象之间的相互循环引用的问题。
例子:
如下代码,对象objA和objB都有字段instance,赋值令objA.instance=objB 及objB.instance=objA,除此之外,这量个对象再无任何引用,但是他们之间因为相互引用着对方,导致它们的引用计数都不为0,于是引用计数法无法通知GC收集器回收它们。
public class RefGC{ public Object instance=null; private static final int _1MB=1024*1024; //给变量赋予一定内存, private byte[] bigSize=new byte[2 * _1MB]; public static void tesetGC(){ RefGC objA=new RefGC(); RefGC objB=new RefGC(); objA.instance=objB; objB.instance=objA; objA=null objB=null; System.gc(); } }
2,跟搜索算法
在主流的商用程序语言中,都是使用根搜索算法(GC Root Tracing)判定对象是否存活的。这个算法的基本思路是通过一系列的名为"GC Roots"的对象作为起点,从这些结点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC roots 没有任何引用链相连时,则证明次对象是不可用的。
在Java 语言里,可作为GC Roots的对象包括 :
1)虚拟机栈(栈桢中的本地变量表)中引用的对象。
2)方法区中的类静态属性引用的对象
3)方法区中的常量引用的对象
4)本地方法栈中JNI(Native方法)的引用对象。