总:垃圾收集算法分为“引用计数式垃圾收集”(Reference Counting GC)和“追踪式垃圾收集”(Tracing GC)。或称为直接垃圾收集和间接垃圾收集。主流java虚拟机用Tracing GC。
三种算法:标记-清除,标记-复制,标记-整理。
在分代收集中:
- 新生代:每次收集都会有大量对象死去,所以可以选择复制算法
- 老年代:对象存活几率高,而且没有额外的空间对它进行分配担保,所以我们必须选择“标记-清除”或“标记-整理”算法进行垃圾收集。因为移动是一个风险动作,移动必须暂停用户应用应用程序才能进行。
一. 标记-清除:标记出所有需要回收的对象,标记完成后统一回收所有被标记的。(也可以反过来标记存活的对象)标记过程是判断对象是否少垃圾的过程。它是最基础的收集算法,后续的算法都是改进它的缺点得到的。
1.缺点:
- 效率问题:如果很多对象,要进行大量标记和清除
- 空间问题(标记清除后会产生大量不连续的碎片)
二.标记-复制(加快了效率,但是缩小了一半内存):将内存分为大小相同的两块,每次使用其中的一 块。当这一块的内存使用完后,就将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。 这样就使每次的内存回收都是对内存区间的一半进行回收。
应用:1.商用java虚拟机用这个来回收新生代(因为存活对象少),因为朝生夕灭的特点,不用1:1比例来划分新生代
2.优化后的Appel式回收:Serial和ParNew采用这种新生代内存布局
新生代:eden区:Survivor(s0区、s1区)=8:1(新生代可用空间为90%)
老年代:tentired 区。
每次分配内存只用Eden和一块Survivor。发生垃圾收集时,将eden和Survivor中存活的对象复制到另一块Survivor区。然后清理掉eden和用过的survivor。如果另一块survivor不够用了,就凭借分配担保将对象放进老年代。分配担保就像去银行借款,信誉好,他就会借你。
三.标记-整理(存活对象多时用这个):让所有存活的对象向一端移动,然后清理掉端边界以外的内存
|