(五)垃圾回收之判定垃圾对象

一、垃圾回收总览

 

 二、判定垃圾对象之引用计数法

  • 引用计数器算法算是一种古老的java垃圾回收算法,目前很多版本的java(jdk1.8也已废弃)已经废弃掉这种算法了。
  • 定义:给每个对象分配一个计算器,当有引用指向这个对象时,计数器加1,当指向该对象的引用失效时,计数器减一。最后如果该对象的计算器为0时,java垃圾回收器会认为该对象是可回收的。
  • 缺陷:
  1. 每次对象被引用时,都需要去更新计数器,有一点时间开销。
  2. 无法解决循环引用问题。
  3. 浪费cpu,即使内存够用,仍然在运行时进行计数器的统计

  2.1  什么是循环引用问题

public class GCTest {

    private Object instance;

    public static void main(String[] args) {

        GCTest gc1 = new GCTest();
        GCTest gc2 = new GCTest();

        gc1.instance = gc2;
        gc2.instance = gc1;

        gc1 = null;
        gc2 = null;

        System.gc();

    }

}
  • 如上述代码,在gc1 = null; gc2 = null; 这两条语句还没执行的时候,如下图,两个对象的计数器值都是2

  • 但是当gc1 = null; gc2 = null; 执行后如下图,两个对象的计数器值都是1,所以对象不会被清理,但是这两个对象其实是垃圾了,这就是循环引用问题。

 

 三、判定垃圾对象之可达性分析算法

  • 这个算法的基本思路就是通过一系列的称谓“GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索所有走过的路径为引用链,当一个对象到GC Roots没有任何引用链项链时,则证明此对象时不可用的:

 

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

 

1) 虚拟机栈(栈帧中的本地变量表)中引用的对象

 

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

 

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

 

4) 本地方法栈中JNI(即一般说的Native方法)引用的对象

 

 

  • 如上图,以栈中的引用为GC ROOTS,对象3和对象4随便彼此引用,但是GC ROOTS无法搜索到,所以对象3和对象4会被当成垃圾清理。

 

posted @ 2017-12-31 22:32  shyroke、  阅读(344)  评论(0编辑  收藏  举报
作者:shyroke 博客地址:http://www.cnblogs.com/shyroke/ 转载注明来源~