如何判定哪些对象为垃圾对象
- 引用计数法
实现方式: 在对象中添加一个引用计数器,当有地方引用这个对象的时候,引用计数器的值就+1,当引用失效的时候,计数器的值就-1,当计数器的值为0的时候,代表这个对象时垃圾对象,可以执行回收
优点: 效率高
缺点: 无法解决对象间循环引用的问题
举例:
/** * 判定哪些内存需要回收,引用计数算法 * -verbose:gc 垃圾回收日志信息 * -xx:PrintGCDetail 打印详细的GC信息 */ public class ReferenceCountDemo { private Object instance; public ReferenceCountDemo() { byte[] m = new byte[20 * 1024 * 1024]; } public static void main(String[] args) { ReferenceCountDemo m1 = new ReferenceCountDemo(); ReferenceCountDemo m2 = new ReferenceCountDemo(); m1.instance = m2; //m1对象引用m2 m2.instance = m1; //m2对象引用m1 m1 = null; //将m1的指针清空 m2 = null; //将m2的指针清空 //将以上指针清空后,由于m1对象和m2对象相互 引用,导致两个对象的计数器都是1,因此不能回收 System.gc(); } }以上例子中m1与m2相互引用,导致不能回收,但我们配置上jvm参数,看一下垃圾回收日志,发现对象被回收了,是因为,垃圾回收器采用的是可达性分析法,因此不必在意上述例子的执行结果,只要明白了是什么意思就可以了!垃圾回收日志如下:
[GC (System.gc()) [PSYoungGen: 23830K->872K(38400K)] 44310K->21360K(125952K), 0.0049954 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [Full GC (System.gc()) [PSYoungGen: 872K->0K(38400K)] [ParOldGen: 20488K->770K(87552K)] 21360K->770K(125952K), [Metaspace: 3303K->3303K(1056768K)], 0.0180230 secs] [Times: user=0.00 sys=0.00, real=0.02 secs]
- 可达性分析法
实现方式: 通过一系列称为"GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连,则证明此对象是不可用的,所以它们将会被判定为可回收的对象。
Java语言中的可作为GC Roots的对象包括:
- 虚拟机栈(局部变量表)引用的对象
- 方法区中类静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中JNI引用的对象
举例:
Obj1及下的两个对象对是GC Root的可达对象,所以不会被当做垃圾对象回收,而Obj4及以下的两个对象不是GC Root的可达对象,所以会被当做垃圾对象回收。
垃圾回收算法
- 标记-清除算法
该算法的两个阶段: ①标记 ②清除
缺点:
1.标记和清除两个过程的效率都不高
2. 标记清除之后会产生大量的内存碎片, 空间碎片太多可能会导致,当要给一个大对象分配内存的时候,没有足够大的 连续内存分配给该大对象,从而会提前出发一次垃圾回收,则又会消耗时间!
- 复制算法
是为了解决标记-清除算法的效率问题,将可用内存按容量划分为大小相等的两块。每次只使用一块,当这块用完了,就将 还存活着的对象复制到另外一块上面。然后再把已使用过的内存空间一次清理掉。
缺点: 空间浪费,将有一般的空间会浪费,当对象存活率较高时,要进行较多的复制操作,因此这种算法不适用老年代
解决空间浪费方案:
堆细分为生存区(Survivor),伊甸园(Eden)和老年代,(Tenured Gen),当创建对象时,将对象放进伊甸园,当伊甸园内存分完之后,会放到其中的一个Survivor区,一般认为生存对象为10%,进行垃圾回收时,会将其中一个Survivor区和Eden中的存活对象复制到另一个Survivor区中,当Survivor区存不下时,就会通过分配担保进入Tenured Gen中。
回收过程如下:
- 标记整理算法
将所有存活的对象移动到一端,将所有所有可回收的对象移动到另一端,直接清理掉端边界以外的内存
- 分代收集算法
根据对象存活周期的不同将内存划分为几块,一般是把java堆分为新生代和老年代。这样就可以根据各个年代的特点采用适当的收集算法。