垃圾回收器就是垃圾回收的实践者,随着JDK的发展,垃圾回收器也在不断的更迭,在不同的场合下使用不同的垃圾回收器,这也是JVM调优的一部分。
1.垃圾回收器的分类
-
按线程可分为单线程(串行)垃圾回收器和多线程(并行)垃圾回收器。
-
按工作模式可分为独占式和并发式垃圾回收器。
-
按工作的区间可分为年轻代垃圾回收器和老年代垃圾回收器。
2.GC的性能指标
GC的性能主要看:
-
吞吐量,运行用户代码所占的总运行时间比例。
-
垃圾收集开销,垃圾收集所占总运行时间的比例。
-
暂停时间,在垃圾回收时,工作线程暂停总花费的时间。
-
对象的存活时间,一个对象从创建到被回收所经历的时间。
3.HotSpot的垃圾回收器
3.1CMS
CMS称Concurrent Mark Sweep,并发标记清除,它在垃圾清除时可以使工作线程和GC线程并发执行,所以在垃圾收集的过程中用户的体验感会好很多。
CMS垃圾回收的过程:
-
初始标记:工作线程暂停,GC标记线程单独工作。
-
并发标记:工作线程和GC线程一起执行。
-
重新标记:工作线程暂停,GC标记线程单独工作。
-
并发清理:工作线程和GC线程一起执行。
如下图所示:
CMS的优点:
-
可以做到并发收集,提升用户的体验感。
CMS的缺点:
-
CMS是基于标记——清除算法的,会存在内存碎片。
-
CMS在并发阶段,CPU资源有限,在并发执行下还是占用了一定的资源的,总吞吐量会变低。
-
CMS无法处理浮动垃圾。
4.三色标记算法
从CMS垃圾收集器开始,引入了三色标记算法,就是将对象的颜色分为了黑、灰、白三种颜色。
黑色:表示该对象确定为存活对象。
灰色:对象已经被扫描,但是还未扫描此对象下的引用。
白色:表示此对象不可达,为垃圾对象。
三色标记的过程:
-
初始确定GC Roots根为黑色对象。
-
将GC Roots根下关联的对象标记为灰色。
-
下一次扫描灰色对象,先将灰色变为黑色,之后将其下的引用标记为灰色。
-
一直重复,直到没有灰色对象。
-
黑色则为存活对象,白色为垃圾对象。
三色标记可能出现的问题:
漏标:
因为CMS中的工作线程和GC线程并发执行的,此时A确定为黑色,B,C为灰色,正常情况下下次应该扫描B了,但是假如此时A与B失去了关联引用,我们发现此时B为灰色,并不能立即直接列为垃圾对象(B就为浮动垃圾),而是需要等到下次GC扫描时,才会发现B是垃圾对象。
错标:
这种情况是B和D开始已经失去了关联,然后将D标记为白色,表示垃圾对象,此时如果突然A和D建立了引用,但是D已经标记为白色了,之后不在会扫描了,之后D就会被当为垃圾对象回收。
解决错标问题的策略:
我们发现错标远比漏标更为严重,错标在同时满足下面两种情况时才会发生:
打破这两种情况的任意一种即可解决错标问题,即利用原始快照或者增量更新。
原始快照:在断开之时,快照将此引用保存下,之后这次扫描完,在以B根重新扫描一次。
增量更新:等建立联系之后,以A根再扫描一次。
5.G1(Garbage First)垃圾优先回收器
G1可以在延迟可控的情况下,尽可能多的增大吞吐量,是一款面向服务端的垃圾收集器,其将堆划分为多个小区域,对各区域内的垃圾数量进行实时检测,优先收集垃圾数量最多的,运用在内存较大的应用上。
6.JDK8默认使用的垃圾回收器
年轻代使用 Parallel Scavenge GC
老年代使用 Parallel Old GC