Java堆里存放着几乎所有的对象实例,垃圾收集器对堆进行回收前,需要确定这些对象哪些死了,哪些还活着。
一、引用计数算法
这个算法给对象添加一个引用计数器,每当有一个地方引用它时,计数器就加1;当引用失败,计数器就减1;任何时刻计数器为0的堆上就是不可能再被使用了。
这个算法有一个问题。很难解决对象之间的互相引用问题。即,当对象A和对象B都有字段instance,令A.instance = B,B.instance = A ,除此之外没有别的引用,但是因为互相引用着,导致他们的引用计数器都不为0,于是这两个对象实例永远无法被回收。
二、可达性分析算法
这个算法基本思路是通过一系列的“GC ROOTS”对象作为起始点,当这些节点开始向下搜索,搜索所走过的路径被称为引用链(Reference Chain),当从GC Roots到一个对象不可达时,则这个对象不可用。
GC Roots对象包括:
- 虚拟机栈(栈帧的局部变量表)中引用的对象。
- 方法区中类静态属性引用的对象。
- 方法区中常量引用的对象。
- 本地方法栈中JNI(即一般说的Native方法)引用的对象。
总结就是,方法运行时,方法中引用的对象;类的静态变量引用的对象;类中常量引用的对象;Native方法中引用的对象。其实还有由系统类加载器(system class loader)加载的对象,以及活着的线程Thread、用于同步的监控对象Monitor Used(不确定) 这里存疑待解答
三、引用的类型
1. 强引用(Strong Reference)
强引用就是new出来的引用。
2. 软引用(Soft Reference)
软引用用来描述一些还有用但是非必需的对象,在系统将要发生内存溢出异常之前,将会将这些对象列入回收范围。
3. 弱引用(Weak Reference)
被弱引用关联的对象只能生存到下一次垃圾收集发生之前。
4. 虚引用(Phantom Reference)
一个对象是否有虚引用,完全对其生存时间无影响,也无法通过虚引用来取得一个对象的实例。唯一目的就是在对象被收集器回收的时候收到一个系统通知。