一.标记清除
标记速度与存活对象线性关系
清除速度与内存大小线性关系
标记清除法分为标记阶段和清除阶段,标记阶段首先找到一些GC Root对象(根对象),根对象是那些一定不能被回收的对象。清除阶段比较简单,加标记的对象保留,没有标记对象清空。缺点:未加标记对象大概率都是不连续,释放之后的内存空间也是不连续的,这会造成内存碎片问题。每一段空闲内存都很小,如果程序需要一段比较大的内存时,则无法满足程序需要。唯一一个使用标记清除法的是CMS的垃圾回收器,他最新版本的jdk,已经将其废弃。
二、标记整理
标记速度与存活对象线性关系
清除与整理速度与内存大小成线性关系
标记整理法是对标记清除法的改进,第一个阶段和标记清除法类似,将未被标记的内存清理,那他多出一个整理阶段,他将存活的对象朝一端靠拢,中间不留空隙,保证内存有一大块连续空间。缺点:效率比较低,因为他需要移动内存空间
三、标记复制
标记与复制速度与存活对象成线性关系
他讲内存分为两个区域from和to,刚开始to区域是空白的,他第一个阶段也是标记root对象,但是他没有清除的动作,他讲root对象的内容复制到to区域,复制完成后,他会将from区域全部清空,这时候to区域用于存对象,from是空闲区域。标记复制法比标记整理法效率更高。缺点:占用了一份额外的内存。
标记复制法一般应用于新生代的垃圾回收,因为新生代存活对象少,只需要少量复制。老年代一般使用标记整理。
四、谈谈GC和分代回收算法
1、GC
GC 的目的在于实现无用对象内存自动释放,减少内存碎片、加快分配速度
GC 要点
①回收区域是堆内存,不包括虚拟机栈,在方法调用结束会自动释放方法占用内存
②判断无用对象,使用可达性分析算法,三色标记法标记存活对象,回收未标记对象
③GC 具体的实现称为垃圾回收器
④GC 大都采用了分代回收思想,理论依据是大部分对象朝生夕灭,用完立刻就可以回 收,另有少部分对象会长时间存活,每次很难回收,根据这两类对象的特性将回收区 域分为新生代和老年代,不同区域应用不同的回收策略
⑤根据 GC 的规模可以分成 Minor GC,Mixed GC,Full GC
2、分带回收算法
分代回收
①伊甸园 eden,最初对象都分配到这里,与幸存区合称新生代
②幸存区 survivor,当伊甸园内存不足,回收后的幸存对象到这里,分成 from 和 to,采用标记复制算法。如下动图,新生代只有6存活,复制过去,剩下清空。
③老年代 old,当幸存区对象熬过几次回收(最多15次),晋升到老年代(幸存区内存不足或大对象会导致提前晋升)
GC 规模
①Minor GC 发生在新生代的垃圾回收,暂停时间短
②Mixed GC 新生代 + 老年代部分区域的垃圾回收,G1 收集器特有
③Full GC 新生代 + 老年代完整垃圾回收,暂停时间长,应尽力避免
五、三色标记与并发漏标问题
1.用三种颜色记录对象的标记状态
①黑色 – 已标记(对象的引用已处理完成)
②灰色 – 标记中 (内部还有引用未处理完成)
③白色 – 还未标记 (还未被处理的)
下动图演示
2.漏标问题 – 记录标记过程中变化
①Incremental Update
只要赋值发生,被赋值的对象就会被记录
②Snapshot At The Beginning,SATB
①新加对象会被记录
②被删除引用关系的对象也被记录
问题如下,右上角白色本来和灰色有一个连线,但是用户层将其断开,白色就会被回收,但是用户层也合一建立白色和黑色的引用,因为黑色已被标志处理完成,故白色无法清理,左下角的白色也是如此。
解决方案两种:增量更新和原始快照。如问题中的黑色即为被复制对象会被记录,垃圾回收线程会监控所有赋值动作,一旦出现赋值就会被记录,换句话说黑色对象变成灰色的,等标记做完,让用户线程先不要运行,再做一次标记,这一遍处理就叫重新标记,这就是增量更新。新分配的对象记录下载,被删除引用关系的对象也会被记录,并发标记结束以后,暂停用户线程,进入重新标记,这就是原始快照。
五、垃圾回收器
Parallel GC
①eden 内存不足发生 Minor GC,标记复制 STW
②old 内存不足发生 Full GC,标记整理 STW
③注重吞吐量
ConcurrentMarkSweep GC
①old 并发标记,重新标记时需要 STW,并发清除
②Failback Full GC
③注重响应时间
G1 GC
①响应时间与吞吐量兼顾
②划分成多个区域,每个区域都可以充当 eden,survivor,old, humongous
③新生代回收:eden 内存不足,标记复制 STW
④并发标记:old 并发标记,重新标记时需要 STW
⑤混合收集:并发标记完成,开始混合收集,参与复制的有 eden、survivor、old,其中 old 会根据暂停时间目标,选择部分回收价值高的区域,复制时 STW
⑥Failback Full GC
第一阶段:新生代回收,刚开始区域都是空闲的,创建对象的时候就会挑选一些区域作为eden区,随着对象越来越多,eden区快要放满,放满了就会触发第一次新生代的垃圾回收。G1新生代内存占比在5%-6%之间波动,采用标记复制法回收,寻找幸存的对象放到survivor区,eden的内存会被释放。随着时间流逝,eden内存又耗尽了,这时候会把eden幸存对象和上一次survivor幸存对象放在一个幸存区,上一次幸存区有一些对象到了晋升阈值,他们就会被放到老年代区。
接下来看看第二个阶段,触发条件,老年代内存越来越多,超过一个阈值,他才会触发标记,默认老年代的占比占掉堆的45%以上时,在老年代标记存活对象,它是并发执行,不会暂停用户线程。并发标记完成,进入第三个阶段,混合收集。他为了不超过设定的暂停时间,他不会一次性回收所有老年代,他会挑出回收价值较高的老年代,这些对象存活数量少,能释放更多内存,连同eden区和幸存区一起做垃圾回收,上次幸存区达到晋升阈值,和老年代幸存的对象放在一个新的老年代区域。在进行多次混合收集,又会进入新生代回收。特殊情况:回收速度小于需要分配新对象速度,这时候并发失败,会触发Failback Full GC,暂停时间比较长。