1.引用计数法:
每个对象有一个引用计数属性,新增一个引用的时候计数加1,引用释放时计数减1,当计数为0的时候就可以回收
2.可达性分析法:
从 GC Roots 开始向下搜索,搜索所走过的路径称为引用链。当一个对象到 GCRoots 没有任何引用链相连时,则证明此对象是不可用的,那么虚拟机就判断是可回收对象。
但是这样会存在一个问题:
引用计数法,可能会出现A 引用了 B,B 又引用了 A,这时候就算他们都不再使用了,但因为相互
引用 计数器=1 ,那这两个对象就都永远无法被回收。
解决:
只靠强引用计数方式,会存在循环引用的问题,导致对象永远无法被释放,弱引用就是专门用来解决循环引用问题的:
若 A 强引用了 B,那 B 引用 A 时就需使用弱引用,当判断是否为无用对象时仅考虑强引用计数是否为 0,不关心弱引用计数的数量
这样就解决了循环引用导致对象无法释放的问题,但这会引发野指针问题:当 B 要通过弱指针访问 A 时,A 可能已经被销毁了,那指向 A 的这个弱指针就变成野指针了。在这种情况下,就表示 A 确实已经不存在了,需要进行重新创建等其他操作
3.GC Roots解释
GC Roots的对象有:
- 虚拟机栈(栈帧中的本地变量表)中引用的对象
- 方法区中类静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中JNI(即一般说的Native方法)引用的对象
可达性算法中的不可达对象并不是立即死亡的,对象拥有一次自我拯救的机会。对象被系统宣告死亡至
少要经历两次标记过程:第一次是经过可达性分析发现没有与GC Roots相连接的引用链,第二次是在由
虚拟机自动建立的Finalizer队列中判断是否需要执行finalize()方法。
当对象变成(GC Roots)不可达时,GC会判断该对象是否覆盖了finalize方法,若未覆盖,则直接将其回
收。否则,若对象未执行过finalize方法,将其放入F-Queue队列,由一低优先级线程执行该队列中对象
的finalize方法。执行finalize方法完毕后,GC会再次判断该对象是否可达,若不可达,则进行回收,否
则,对象“复活”