引用计数法的应用场景:
• 建议不要用
4.4.2 可达性分析法
- 该种方法是从GC Roots开始向下搜索,搜索所走过的路径为引用链。当一个对象到GC Roots没用任何引用链时,则证明此对象是不可用的,表示可以回收。
上图上图中Object1、Object2、Object3、Object4、Object5到GC Roots是可达的,表示它们是有引用的对象,是存活的对象不可以进行回收
Object6、Object7、Object8虽然是互相关联的,但是它们到GC Roots是不可达的,所以他们是可以进行回收的对象。
那些可以作为GC Roots 的对象:
1、虚拟机栈(栈帧中的本地变量表)中引用的对象;
2、方法区中类静态属于引用的对象;
3、方法区中常量引用的对象;
4、本地方法栈中JNI(即一般说的Native方法)引用的对象。
等
可达性算法的优点:
解决相互循环引用问题。
可达性算法的优点:
目前和引用计数法比没得缺点
可达性算法的应用场景:
这是目前主流的虚拟机都是采用的算法
4.5 垃圾回收机制策略(也称为GC的算法)
4.5.1 引用计数算法(Reference counting)
每个对象在创建的时候,就给这个对象绑定一个计数器。每当有一个引用指向该对象时,计数器加一;每当有一个指向它的引用被删除时,计数器减一。这样,当没有引用指向该对象时,计数器为0就代表该对象死亡,这时就应该对这个对象进行垃圾回收操作。
引用计数法的优点:
引用计数算法的实现简单,判定效率也很高。
引用计数法的缺点:
主流的Java虚拟机里面没有选用引用计数算法来管理内存,其中最主要的原因是它很难解决对象之间相互循环引用的问题。
例如:
package com.lijie;
public class Test {
public Object object = null;
public static void main(String[] args) {
Test a = new Test();
Test b = new Test();
/**
* 循环引用,此时引用计数器法失效
*/
a.object = b;
b.object = a;
a = null;
b = null;
}
}
引用计数法的应用场景:
建议不要用
4.5.2 标记–清除算法(Mark-Sweep)
为每个对象存储一个标记位,记录对象的状态(活着或是死亡)。
分为两个阶段,一个是标记阶段,这个阶段内,为每个对象更新标记位,检查对象是否死亡;第二个阶段是清除阶段,该阶段对死亡的对象进行清除,执行 GC 操作。
标记清除算法的优点:
是可以解决循环引用的问题
必要时才回收(内存不足时)
标记清除算法的缺点:
回收时,应用需要挂起,也就是stop the world。
标记和清除的效率不高,尤其是要扫描的对象比较多的时候
会造成内存碎片(会导致明明有内存空间,但是由于不连续,申请稍微大一些的对象无法做到),
标记清除算法的应用场景:
该算法一般应用于老年代,因为老年代的对象生命周期比较长。
4.5.3 标记–整理算法
标记清除算法和标记压缩算法非常相同,但是标记压缩算法在标记清除算法之上解决内存碎片化(有些人叫"标记整理算法"为"标记压缩算法")
标记-整理法是标记-清除法的一个改进版。同样,在标记阶段,该算法也将所有对象标记为存活和死亡两种状态;不同的是,在第二个阶段,该算法并没有直接对死亡的对象进行清理,而是将所有存活的对象整理一下,放到另一处空间,然后把剩下的所有对象全部清除。这样就达到了标记-整理的目的。