串行垃圾收集器
串行垃圾收集器,是指使用单线程进行垃圾回收,垃圾回收时,只有一个线程在工作,Java应用中的所有线程都要暂停,等待垃圾回收的完成。这种现象称之为STW(Stop-The-World),一般的javaweb应用中不会采用这种收集器
并行垃圾收集器
并行垃圾收集器是在串行的基础上做了改进,将单线程改为了多线程,但在收集的过程中仍会暂停应用程序,只是并行执行,速度更快,暂停的时间更短。
ParNew垃圾收集器
该垃圾收集器工作在年轻代上,通过-XX:+UserParNewGC参数设置,老年代仍然是串行垃圾收集器。
ParallelGC垃圾收集器
该收集器是在ParNewGC的基础上新增了两个参数,使得使用起来更灵活高效。
相关参数如下:
- -XX:+UseParallelGC
- 年轻代使用ParallelGC收集器,老年代串行
- -XX:+UseParallelOldGC
- 年轻代和老年代都使用该收集器
- -XX:+MaxGCPauseMillis
- 设置最大的垃圾收集的停顿时间,单位毫秒
- 设置该参数可能会调整堆的大小或其他的参数,如果堆的大小设置的过小,就 会GC工作的频繁,反而会影响性能
- -XX:UseAdaptiveSizePolicy
- 自适应GC模式,垃圾回收器将自动调整新生代和老年代等参数,达到吞吐量,堆大小、停顿时间之间的平衡
- 一般用于手动调整参数比较困难的场景,让收集器自动进行调整
- -XX:GCTimeRatio
- 设置垃圾回收时间占程序运行时间的百分比,公式为1/(1+n)
- 它的值在0~100之间,默认值为99,即垃圾回收时间不超过1%
CMS垃圾收集器
CMS全称Concurrent Mark Sweep,是一款并行的,使用标记清除算法的收集器,该收集器是针对老年代进行垃圾回收的,通过-XX:+UserConcMarkSweepGc进行设置。执行过程如下:
- 初始化标记(CMS-initial-mark),标记root,会导致stw;
- 并发标记(CMS-concurrent-mark)。与用户线程同步进行
- 预清理(CMS-concurrent-preclean).与用户线程同时运行
- 重新标记(CMS-remark),会导致stw
- 并发清除(CMS-concurrent-sweep),与用户线程同时运行
- 调整堆大小,设置CMS在清理之后进行内存压缩,目的是清理内存中的碎片
- 并发重置状态等待下次CMS的触发(CMS-concurrent-reset),与用户线程同时进行
G1垃圾收集器
原理
G1垃圾收集器相对于其他收集器而言,最大的区别在于取消了年轻代、老年代的物理划分,取而代之的是将堆划分为若干个区域(Region),这些区域包含了有逻辑上的年轻代、老年代区域,各代的存储是不连续的,每一代都是用n个不连续的大小相同的区域,每个区域占有一块连续的虚拟内存地址。如下图:
这样的好处就是不用对单独的空间进行设置,不用担心内存不足
每个内存分段都可以被标记为Eden区,Survivor区,Old区和Humongous区,这样属于不同代,不同区的内存分段就可以不必连续了。
G1中有一个特殊的区域:Humongous区。如果一个对象占用的空间超过了分区容量(Region)的50%,G1收集器会默认该对象是一个巨大对象(humongous object,H-obj),该对象有以下特征:
- 默认直接分配到年老代,防止反复拷贝移动。
- 该对象在并发标记清理阶段和Full GC阶段回收不再存活的对象
- 在分配巨型对象之前先检查java堆占用率阈值,如果超过的话就启动并发标记,为的是提早回收从而防止Evacuation Failures 和Full GC
Young GC
Young GC主要是对Eden区进行GC,它在Eden空间被耗尽时会被触发
- Eden空间的数据移动到Survivor中,如果Survivor空间不够,Eden区的部分数据会直接到年老代
- Survivor区的数据移动到新的Survivor区中,部分数据到年老代空间中
- 最终Eden空间的数据为空,GC停止工作,应用线程继续执行。
- Remember Set(Rset,已记忆集合)
G1中引入了RSet的概念,其作用是跟踪指向某个对象的跟踪引用
在每个分区内部又被分为了若干个大小为512byte的卡片(card),标记对内存的最小可用粒度。所有分区的卡片将会记录在全局卡片表(Global Card Table)中,分配的对象会占用物理上连续的若干个卡片,当查找对分区内对象的引用时便可以通过记录卡片来查找该引用你对象。每次对内存的回收,都是对指定分区的卡片进行处理。
Mixed GC
当越来越多的对象到Old区中,为了避免内存被耗尽,虚拟机 会触发混合的垃圾回收机制,即(Mixed GC),该算法不是一个Old GC,除了回收年轻代之外,还会回收一部分的年老代,可以控制堆哪些年老代回收,从而控制垃圾回收的时间,也需要注意的是:Mixed GC不是Full GC
MIxed GC什么时候触发,是由参数XX:InitiatingHeapOccupancyPercent 决定,默认45%。该参数的意思是:当年老代大小占整个堆大小的百分比。
它的GC分为两步
1、全局并发标记 2、拷贝存活对象(evacuation)
- 全局并发标记
- 初始标记
- 标记从根节点直接可达的对象,这个阶段会执行一次年轻代GC,产生全局停顿
- 根区域扫描
- G1 GC在初始标记的存活区扫描对年老代的引用,并标记被引用的对象
- 该阶段和应用程序(非STW)同时运行,并且只有完成该阶段后,才开始下一次STW的年轻代回收
- 并发标记
- G1 GC在整个堆中查找存活的对象。该阶段和应用程序同时进行,可以被STW年轻代回收终端
- 重新标记
- 该阶段是STW回收,因为程序在运行,对上一次的标记进行修正
- 清理垃圾
- 清点和重置标记状态,该阶段会进行STW,整个阶段并不实际区垃圾回收。等待evacuation阶段回收
- 初始标记
- 拷贝存活对象
Evacuation阶段是全暂停的。该阶段把一部分Region中的存活对象拷贝到另一部分的Region中,从而实现垃圾清理
Full GC
略