JDK1.4 Update14 Based Hotspot JVM中7种垃圾收集器简介

  • 新生代收集器
    • Serial
    • ParNew
    • Parallel Scavenge
    • G1
  • 老年代收集器
    • CMS
    • Serial Old (MSC)
    • Parallel Old
    • G1

__下图展示了垃圾收集器之间的协同关系,被连线的GC可以搭配使用 __
来源:https://blogs.oracle.com/jonthecollector/our-collectors

1. Serial 收集器(新生代)

Serial收集器是最基本,历史最悠久的单线程收集器,使用复制算法进行新生代垃圾收集。它是单线程运作,并且需要在进行垃圾收集时暂停其他工作线程直至垃圾回收结束(Stop the world)。虽然有这个缺陷,但是它仍能够在单线程环境下简单高效地进行垃圾回收。因此Serial收集器通常用于Client环境。

2. ParNew 收集器(新生代)

Serial收集器的多线程版本,同样使用复制算法进行新生代垃圾收集,除此之外与Serial几乎一样。他的一大优势是可以和老年代收集器CMS配合工作。在CPU甚至双核CPU环境下ParNew并不比Serial表现更好,但是在更多CPU(如今的服务器平台甚至有32核甚至以上的处理器)的环境下,ParNew能够拥有很好的表现,所以它常被用于Server环境。

3. Parallel Scavenge 收集器(老年代)

Parallel Scavenge 同样是一款多线程并行垃圾收集器,采用复制算法对新生代进行垃圾回收。他与ParNew的不同之处在于,他可以对吞吐量(吞吐量 = 运行用户代码的时间 / (运行用户代码的时间 + GC时间))进行人为控制,这在后台运行,没有太多交互的情况下非常有用,所以它也被称为吞吐量优先收集器。在交互较多的情况下,ParNew和Serial能够尽可能缩短GC暂停时间,以提高用户体验(试想一下,如果在使用程序时,程序不停地暂停进行垃圾回收是一件多么恼人的事情)。但是在后台运行,不需要太多交互的情况下,高吞吐量可以使程序的总运行时间缩短,从而提高工作效率。

举一个简单的例子,一款程序,在使用Serial或ParNew的情况下,当程序每运行10秒,则进行100 ms的垃圾回收,在运行10分钟后,就总共进行了60 * 100 ms = 6000ms即6秒的垃圾回收。虽然所耗总时间较长,但是每次较短时间的GC不会被用户察觉,从而提供流畅的交互体验。如果使用Parallel Scavenge,程序可以在进行10分钟用户代码运行后,进行5秒的垃圾回收(由于不需要频繁地进行线程切换、暂停操作,其进行等量垃圾回收工作所需的时间会较小),这样总运行时间就比Serial或ParNew更短。这样的优势在大型项目,长时间运行服务器的情况下是收益巨大的。同时,长停顿时间并不会给交互量较小的程序带来太多体验上的劣势。

除此之外,这样的模式还能带来较大的新生代空间。为了缩短单次GC时长,ParNew和Serial等收集器通常将新生代空间限制得较小,这会造成GC次数变多。而高吞吐量的Parallel Scavenge则可以提供更大新生代空间,给予程序更多地可用资源。

Parallel Scavenge还有一个有用的功能:自适应策略调整。打开该功能后,它会根据当前情况自动设置合理的新生代空间,吞吐量,进行内存管理,以达到最大工作效率。这也是一个非常有用的功能。

4. Serial Old 收集器(老年代)

Serial 收集器的老年代版本,采用“标记—整理”算法,通常用于与Parallel Scavenge搭配使用,或者作为CMS收集器的后备方案,用以应对并发模式失败的情况。其他方面都与Serial收集器大同小异,不再赘述。

5. Parallel Old 收集器(新生代)

Parallel Scavenge 收集器的老年代版本,使用多线程和“标记—整理”算法。它能够与Parallel Scavenge搭配使用,从而最大化GC的多线程能力,并且使整个GC系统都是吞吐量优先,是用于后台少交互程序的重要组合。在Parallel Old出现在JDK 1.6中之前,Parallel Scavenge只能选择Serial Old单线程收集器,这样尴尬的组合极大地浪费了多线程资源和吞吐量优势。

6. CMS 收集器(老年代)

CMS是一款以最短回收停顿时间为主要优先的回收器。在Java Web开发和B/S系统服务端中,响应速度非常重要,CMS完美契合了这种需求。他的运作方式相较前几种收集器更为复杂,基于“标记-清除算法”实现,主要过程可以划分为:

  • 初始标记
  • 并发标记
  • 重新标记
  • 并发清除

这款收集器有一个重大优势,即是它实现了一定的并发 (Concurrent) 运算能力。在上面的四个过程中,耗时最长的并发标记和并发清除都是与用户线程并发进行的,这大大缩短了GC时的停顿时间。

CMS虽然极大缩短了停顿时间,但是带来了三个缺点:

  1. CPU资源敏感:它在CPU核心数较少(4个以下)时,会占据大量的运算资源,导致用户线程执行效率降低。这是因为它需要占据一个线程与用户线程并发工作,当CPU核心数为2时,他需要占据一整个线程,使运算效能下降50%,这是难以接受的。所以他通常被用在高核心数CPU平台。同时,为了解决这个缺陷,虚拟机 提供了被称为“增量式CMS”的CMS变种。它能够在单线程上和用户线程交替运行,减少GC线程独占资源的时间,虽然延长了总时间,但是对用户影响不大。目前这个技术已经不被官方提倡使用。
  2. 没有浮动垃圾(Floating Garbage)处理能力:在并发情况下,并发标记之后也可能会产生新的垃圾(与非并发的快照模式不同),CMS由于已经完成标记,所以这部分新产生在标记之后的垃圾被称为浮动垃圾,无法在本次GC中回收。在这种情况下,如果浮动垃圾造成了内存溢出,则会导致一次"Concurrent Mode Failure"(并发模式失败)错误,这是虚拟机会启用备选方案进行垃圾回收(临时启用Serial Old),而这又会降低运行效率。这个问题的解决方式就是不要将CMS的触发阈值调得太高,在内存占用率较低的时候就启用CMS进行垃圾回收,以留给更多空间给CMS运行时其他并发运行的线程使用。
  3. 标记—清除算法造成的碎片化空间:由于采用标记-清除算法,在清除后,被释法的内存空间没有进行排序,可用的内存空间可能不连续,形成碎片化空间。在遇到大容量对象时,就可能出现无法找到可用空间的情况,从而触发一次Full GC。为了解决这个问题,CMS提供了一个在到达Full CG触发临界条件前,进行一次内存碎片合并整理的功能(默认开启)。但是由于这项功能不能并发进行,停顿时间将会延长。此外,JVM还提供了压缩的Full CG用于应对极端情况。当一定次数(可设置)的无压缩Full CG后仍然无法分配空间,则会进行一次压缩Full CG。

7. G1收集器

G1收集器是当前最前沿的CG技术。G1是一款面向服务器端的垃圾收集器,他是用于替代CMS的产品,拥有以下特征:

  • 并行与并发处理:能够最大化利用多CPU,多核,多线程环境来缩短CG停顿时间,并且能够与用户线程并发进行。
  • 分代收集:它可以同时用于处理不同代的垃圾,不需要其他回收器配合,独立管理整个GC堆,并且也能根据回收对象存活时间的不同选择不同的方式和算法(真他妈牛逼)。G1没有将GC堆物理划分为新生代和老年代(像上述其他回收器一样),而是将整个JAVA堆划分为大小相同的多个区域(region),用于存放不同代的对象。
  • 空间整合:G1从整体来看是基于“标记-整理”算法,从局部来看使用“复制”算法,这两种算法都不会产生碎片化空间,解决了CMS碎片化空间的问题。
  • 可预测的CG停顿:G1除了能够大幅度缩短GC停顿时间,也能够建立可预测停顿模型,让用户自行指定GC频率和单次GC最大时间,这几乎实现了实时JAVA垃圾收集(RTSJ)。这个功能实现基于上述的多区域(region)布局策略,G1能够追踪不同Region中对象的存活时长,评估其回收优先级,建立回收优先列表,总是从优先级最大的Region开始回收(这也是G1—Garbage First名字的由来),保证了G1在单次指定有限GC时间内获得最大的回收效率和价值。

G1的Region划分内存规划具体实现十分复杂,因为Region之间的关联性难以被打破,当整个JAVA堆被划为不同region时,也意味着每次GC都需要对所有region进行全局扫描,来判断对象的引用链。在以前的老年代-新生代划分模型中,新生代往往容量较少,扫描较快,GC更频繁,而老年代容量较大,扫描较慢吗,但是GC次数相对相低,两个区域独立进行垃圾回收,所以这个问题不明显。在G1中,JVM使用Remembered Set技术避免全堆扫描,其具体内容在这里不进行赘述。

除开Remembered Set,G1 的GC过程可以分为以下步骤:

  • 初始标记
  • 并发标记
  • 最终标记
  • 筛选回收

G1回收器目前还不是非常成熟,还处于改进发展中,未来将大有作为。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值