(1)引用计数算法:给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值加1;当引用失效时,计数器减1;任何时刻计数器都为0的对象就是不可能再被使用的。实现简单,判断效率高,Java没有选用主要因为它很难解决对象相互循环引用的问题。
Java采用的方式:(1)可达性分析:"GC Roots"的对象作为起始点,从这些节点开始向下搜索,当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的,下图对象object5, object6, object7虽然有互相判断,但它们到GC Roots是不可达的,所以它们将会判定为是可回收对象。Java通过有向图来记录和管理堆内存中的所有对象。
可作为GC Roots对象的包括如下几种:
a.虚拟机栈(栈桢中的本地变量表)中的引用的对象
b.方法区中的类静态属性引用的对象和常量
d.本地方法栈中JNI的引用的对象
(2)finalize()方法最终判定对象是否存活
不可达的对象并非是“非死不可”的,不可达的对象要经历两次标记筛选。
1).第一次标记筛选:此对象是否有必要执行finalize()方法。
当对象没有覆盖finalize方法,或者finzlize方法已经被虚拟机调用过,虚拟机将这两种情况都视为“没有必要执行”,对象被回收。
2).第二次标记:低优先级的finalize线程
有必要执行finalize方法的对象将会被放置在F-Queue的队列之中,并在稍后由一条虚拟机自动建立的、低优先级的Finalizer线程去执行。这里所谓的“执行”是指虚拟机会触发这个方法,但并不承诺会等待它运行结束。这样做的原因是,如果一个对象finalize()方法中执行缓慢,或者发生死循环,将很可能会导致F-Queue队列中的其他对象永久处于等待状态,甚至导致整个内存回收系统崩溃。
Finalize()方法中只要重新与引用链上的任何的一个对象建立关联即可,譬如把自己this赋值给某个类变量或对象的成员变量,那么就逃离死亡
2、回收方法区:
新生代一次垃圾收集一般回收75~95%的空间,而永久代(方法区)比较低。永久代的回收主要分为:废弃常量和无用的类。
废弃常量:常量池中有字符串“abc”,但是当前系统没有任何地方引用该常量的
无用的类:同时满足:该类的所有实例被回收,加载该类的classLoader被回收,Java.lang.class在任何地方没有再引用。