初步了解JVM第三篇垃圾收集器

垃圾回收器是垃圾回收算法的具体实现。新生代、老年代的垃圾回收器必须按照hotspot的要求成对组合进行使用(需要根据JDK的版本以及实际业务进行选择)

一、垃圾回收器算法:

  • 分代收集理论:这是目前虚拟机使用的回收算法,它将内存分为不同的代(如新生代和老年代)。新生代使用复制算法,老年代使用标记-整理算法。这种方法结合了不同算法的优点,提高了垃圾回收的效率‌。
  • 复制算法:在复制算法中,内存被分为两块,每次使用其中一块。当这块内存用完时,将存活的对象复制到另一块上,并清除当前内存块中的所有对象。这种方法适用于存活对象较少的情况,因为它只需要扫描一次内存。缺点是需要一块空的内存空间,并且需要复制移动对象‌
  • 标记整理算法:这种算法在标记阶段标记所有存活的对象,然后将存活的对象压缩到内存的一端,清理边界外的所有空间。这种方法避免了内存碎片的产生,适用于老年代对象‌
  • 标记清理算法:这是最基本的垃圾回收算法之一。它分为两个阶段:标记阶段和清除阶段。在标记阶段,从根节点(GC Roots)开始,标记所有从根节点开始的对象。在清除阶段,清除所有未被标记的对象。这种算法适用于存活对象较多的情况,但缺点是容易产生内存碎片‌

   二、‌垃圾回收器种类及其特点‌:

  • 单线程垃圾收集器‌:如Serial和Serial Old,适用于单核处理器环境,简单高效‌。应用场景:适用于客户端应用程序或者硬件资源有限的环境

  • 多线程垃圾收集器‌:如Parallel Scavenge和Parallel Old,适用于多核处理器环境,可以并行处理垃圾回收任务,提高效率‌。应用场景:一些后台计算任务、大数据处理等场景

  • 并发垃圾收集器‌:如ParNew和CMS,可以在垃圾回收时应用继续运行,减少停顿时间‌。应用场景:服务器端应用

  • 智能并发垃圾收集器‌:如G1,能够根据应用程序的运行情况动态调整垃圾回收策略,适用于大内存应用‌ 

  三、详解垃圾收集器:

3.1 Serial收集器(-XX:+UseSerialGC -XX:+UseSerialOldGC)

Serial(串行)收集器是最基本、历史最悠久的垃圾收集器了。意味着它只会使用一条垃圾收集线程去完成垃圾收集工作,更重要的是它在进行垃圾收集工作的时候必须暂停其他所有的工作线程( "Stop The World" ),直到它收集结束。 新生代(Serial)采用复制算法,老年(serial old)代采用标记-整理算法。
Serial Old收集器是Serial收集器的老年代版本, 主要两大用途:一种用途是在JDK1.5以及以前的版本中与Parallel Scavenge收集器搭配使用,另一种用途是作为CMS收集器的后备方案

3.2 Parallel Scavenge收集器(-XX:+UseParallelGC(年轻代),-XX:+UseParallelOldGC(老年代))

Parallel 收集器其实 就是Serial收集器的多线程版本 ,除了使用多线程进行垃圾收集外,其余行为(控制参数、收集算法、回收策略等等)和Serial收集器类似。默认的收集线程数跟cpu核数相同,当然也可以用参数(-XX:ParallelGCThreads)指定收集线程数,但是一般 不推荐修改。
Parallel Scavenge收集器关注点是吞吐量(高效率的利用CPU)。CMS等垃圾收集器的关注点更多的是用户线程的停顿时间(提高 用户体验)。所谓吞吐量就是CPU中用于运行用户代码的时间与CPU总消耗时间的比值。 Parallel Scavenge收集器提供了很多参数 供用户找到最合适的停顿时间或最大吞吐量,如果对于收集器运作不太了解的话,可以选择把内存管理优化交给虚拟机去完成也是一 个不错的选择。
Parallel Old收集器是Parallel Scavenge收集器的老年代版本 。使用多线程和“标记-整理”算法。在注重吞吐量以及CPU资源的场合,都可以优先考虑 Parallel Scavenge收集器和Parallel Old收集器(JDK8默认的新生代和老年代收集器),JDK 1.6 之后引入了 Parallel Old 收集器。

3.3 ParNew收集器(-XX:+UseParNewGC)

ParNew收集器其实 跟Parallel收集器很类似 ,区别主要在于它可以和CMS收集器配合使用。
新生代采用复制算法 它是许多运行在Server模式下的虚拟机的首要选择,ParNew 收集器是 Serial 收集器的多线程版本, 只有它能与CMS收集器配合工作。,它使用多个线程同时进行垃圾回收,从而提高了垃圾回收的效率。在进行垃圾回收时,同样会暂停所有的用户线程。与 Serial 收集器相比,ParNew 收集器在多核心处理器的环境下能够充分利用 CPU 资源,加快垃圾回收的速度。

3.4 CMS收集器(-XX:+UseConcMarkSweepGC(old))

CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。它非常符合在注重用户体验的应用上使 用,它是HotSpot虚拟机第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程(基本上)同时工作。 从名字中的 Mark Sweep 这两个词可以看出,CMS收集器是一种 “标记-清除”算法 实现的。

整个过程分为四个步骤:

初始标记: 暂停所有的其他线程 (STW) ,并记录下 gc roots 直接能引用的对象 速度很快 (白色)
并发标记: 并发标记阶段就是从 GC Roots 的直接关联对象开始遍历整个对象图的过程, 这个过程耗时较长但是不需要停顿用户线程, 可以与垃圾收集线程一起并发运行。因为用户程序继续运行,可能会有导致已经标记过的对象状态发生改变。 (灰色--》直到变黑)
重新标记: 重新标记阶段就是为了修正并发标记期间因为用户程序继续运行而导致标记产生变动的那一部分对象的标记记录 ( 主要 是处理漏标问题 ) ,这个阶段的停顿时间一般会比初始标记阶段的时间稍长,远远比并发标记阶段时间短。 主要用到三色标记里的 增量 更新算法做重新标记。
并发清理: 开启用户线程,同时 GC线程开始对未标记的区域做清扫。这个阶段如果有新增对象会被标记为黑色不做任何处理 (理论上所有可达的对象都应该是黑色
并发重置: 重置本次 GC 过程中的标记数据。
扩展三色标记:
  1. 黑色(Black):黑色对象是已经访问过的对象,并且其所有引用(指向其他对象的引用)都已经扫描过。如果一个对象是黑色的,那么垃圾回收器可以确定这个对象及其所有可达的子对象都不会被回收。

  2. 灰色(Gray):灰色对象是已经被访问过,但是其引用(指向其他对象的引用)还没有完全扫描的对象。垃圾回收器正在处理这些对象的引用,以便将它们标记为黑色或再次标记为灰色(如果它们指向了新的未访问对象)。

  3. 白色(White):白色对象是最初未被访问到的对象,即它们没有被标记为可达的。理论上,这些对象可以被回收。

  4. 优点和挑战

    (1)优点

  • 允许垃圾回收器在不停止整个应用程序的情况下进行部分垃圾回收。

  • 提高了垃圾回收的效率,减少了停顿时间。

    (2)挑战

  • 实现复杂:需要精确控制并发执行和重新检查阶段的逻辑。

  • 浮动垃圾问题:即使在重新检查阶段也可能出现浮动垃圾。

  • 并发控制:必须小心处理并发执行中的线程安全问题。

四、G1

G1 (Garbage-First)是一款面向服务器的垃圾收集器, 主要针对配备多颗处理器及大容量内存的机器。  以极高概率满足GC 停顿时间要求的同时,还具备高吞吐量性能特征。在JDK7u4版本 中正式推出,在JDK9中为默认的垃圾收集器。
  • G1分区基本思路:G1将Java堆划分为多个大小相等的独立区域(Region),JVM最多可以有2048个Region。一般Region大小等于堆大小除以2048,比如堆大小为4096M,则Region大小为2M,当然也可以用参数"-XX:G1HeapRegionSize"手动指定Region大小,但是推荐默认的计算方式。默认新生代占整体的5%,可以通过“-XX:G1NewSizePercent”设置新生代初始占比
  • 分区类型:自由分区、新生代分区、大对象分区、老年代分区
  • 什么场景适合使用G1
    1. 50%以上的堆被存活对象占用
    2. 对象分配和晋升的速度变化非常大
    3. 垃圾回收时间特别长,超过1秒
    4. 8GB以上的堆内存(建议值)
    5. 停顿时间是500ms以内

五、ZGC

在2018年9月发布的JDK 11(linux/x64)中,ZGC作为实验性质的特性被正式引入JVM中,在JDK15中正式成为特性.

详情可以参考:【JVM】JVM垃圾收集器:ZGC垃圾收集器深入解析_zgc垃圾回收器-优快云博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值