收集算法是内存回收的方法论,那垃圾收集器就是内存回收的实践者
上图展示了七种作用于不同分代的收集器,如果两个收集器之间存在连线,就说明他们可以搭配使用。图中收集器所在的区域,则表示它是属于新生代收集器抑或是老年代收集器。
1. Serial收集器
Serial收集器是最基础、历史悠久的收集器,同时他也是一个单线程工作的收集器。
优点:与其他收集器相比,简单而高效、它是所有收集器里消耗最小的,同时效率最高的单线程。
缺点:会“Stop the World”
当前:依旧是HotSpot虚拟机运行在客户端下默认的新生代收集器。
推荐:在客户端使用。
算法:标记-复制
2. ParNew收集器
ParNew收集器实质上是Serial收集器的多线程并行版本。
优点:低概率出现“Stop the world”
缺点:存在线程交互的开销,效率比Serial低。
当前:JDK9前使用ParNew搭配CMS
推荐:服务端
算法:标记-复制
3. Parallel Scavenge收集器
派瑞啦斯堪瑞吉
Parallel Scavenge目标是达到一个可控制的吞吐量:
用户可以设置控制最大垃圾收集停顿时间,和直接设置吞吐量大小。
算法:标记-复制
4. Serial Old收集器
Serial Old收集器是Serial收集器的老年代版本,使用单线程。
优点:单线程,快
缺点:可能会出现“Stop the world”
当前:JDK5之前是Parallel+Scavenge的后备预案。
推荐:客户端
算法:标记-整理
5. Parallel old 收集器
Parallel Scavenge收集器的老年代版本,使用多线程并发收集。
优点:降低“Stop the world”的概率
缺点:加大系统资源的使用
当前:JDK5之前是Parallel+Scavenge的后备预案。
推荐:注重吞吐率和处理资源较为稀缺的环境。比如大数据
算法:标记-整理
6. CMS收集器
CMS收集器是一种以获取最短回收停顿时间为目标的收集器。
优点:并发收集、低停顿
缺点:CMS收集器对处理器资源非常敏感
,CMS无法处理“浮动垃圾”,有可能出现并发失败而进行Full GC
,标记-清除会产生大量碎片化空间
当前:JDK5之前是Parallel+Scavenge的后备预案。
推荐:系统停顿时间尽可能短,已给客户带来更好的交互体验。B/S系统
算法:标记-清除算法
标记阶段并发:增量更新
运作过程
-
初始标记:标记一下GC Roots能直接关联到的对象,速度很快,会“STW”
-
并发标记:从GC Roots的直接关联对象开始遍历整个对象图的过程,耗时较长
-
重新标记:为了修正并发标记期间,因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录。会“STW”
-
并发清除:清理删除标记阶段判断已经死亡的对象。
7. G1收集器
Garbage First ( 简称G1)收集器是垃圾收集器技术发展历史上的里程碑式的成果,它开创了收集 器面向局部收集的设计思路和基于Region的内存布局形式。被官方称之为“全能的垃圾回收器”。
目标:在延迟可控的情况下获得尽可能高的吞吐量。
特点:G1面向堆内存来组成回收集来进行回收,衡量标准不再是它属于哪个分代,而是哪块内存内存中存放的垃圾数量最多,回收收益最大,这就是G1收集器的Mixed GC模式。
Region堆:实现Mixed GC模式的关键。G1不再坚持固定大小以及固定数量的分代区域划分,而是把连续的Java堆划分为多个大小相等的独立区域(Region),每一个Region都可以根据需要,扮演新生代的Eden空间、Survivor空间,或者老年代空间。
Humongous区域:Region中还有一类特殊的Humongous区域,专门用来存储大对象,只要改对象大小超过Region容量一般就判定为大对象。
更具体的处理思路是让G1收集器去跟踪各个Region里面的垃圾堆积的“价值”大小,价值即回收所获得的空间大小以及回收所需时间的经验值,然后在后台维护一个优先级列表,每次根据用户设定允许的收集停顿时间(使用参数-XX: M axGCPauseMilis指定,默认值是200毫秒),优先处理回收价值收益最大的那些Region,这也就是“Garbage First”名字的由来。这种使用Region划分内存空间,以及具有优先级的区域回收方式,保证了G1收集器在有限的时间内获取尽可能高的收集效率。
缺点:
-
跨Region对象的回收要比其他收集器的效率低。
-
并发标记阶段,如果内存回收的速度赶不上内存分配的速度,G1会冻结用户线程,导致触发Full GC而产生的“STW”。
运行过程步骤:
-
初始标记( Initial Marking) :仅仅只是标记一下GC Roots能直接关联到的对象,并且修改TAMS指针的值,让下一阶段用户线程并发运行时,能正确地在可用的Region中分配新对象。这个阶段需要停顿线程,但耗时很短,而且是借用进行MinorGC的时候同步完成的,所以G1收集器在这个阶段实际并没有额外的停顿。
-
并发标记(Concurrent Marking) :从GC Root开始对堆中对象进行可达性分析,递归扫描整个堆里的对象图,找出要回收的对象,这阶段耗时较长,但可与用户程序并发执行。当对象图扫描完成以后,还要重新处理SATB记录下的在并发时有引用变动的对象。
-
最终标记(FinalMarking):对用户线程做另一个短暂的暂停,用于处理并发阶段结束后仍遗留下来的最后那少量的SATB记录。
-
筛选回收( Live Data Counting and Evacuation) :负责更新Region的统计数据,对各个Region的回收价值和成本进行排序,根据用户所期望的停顿时间来制定回收计划,可以自由选择任意多个Region构成回收集,然后把决定回收的那一部 分Region的存活对象复制到空的Region中,再清理掉整个旧Region的全部空间。这里的操作涉及存活对象的移动,是必须暂停用户线程,由多条收集器线程并行完成的。
整体看:标记-清除
局部看:标记-复制
标记阶段并发:原始快照