Salmon的全栈知识 Salmon的全栈知识
首页
  • JavaSE
  • JavaWeb
  • Spring生态
  • JUC
  • JVM
  • Netty
  • Java各版本特性
  • 23种设计模式
  • Maven
  • Java常用框架
  • Dubbo
  • OpenFeign
  • Nacos
  • Zookeeper
  • Sentinel
  • Seata
  • Gateway
  • Go基础
  • Gin
  • SQL数据库

    • MySQL
    • Oracle
  • NoSQL数据库

    • Redis
    • MongoDB
    • ElasticSearch
  • 消息中间件

    • RabbitMQ
    • RocketMQ
    • Kafka
    • ActiveMQ
    • MQTT
    • NATS
  • 网关中间件

    • Nginx
  • Linux
  • Docker
  • Git
  • K8s
  • Solidity
  • Java
  • 计算机网络
  • 操作系统
GitHub (opens new window)
首页
  • JavaSE
  • JavaWeb
  • Spring生态
  • JUC
  • JVM
  • Netty
  • Java各版本特性
  • 23种设计模式
  • Maven
  • Java常用框架
  • Dubbo
  • OpenFeign
  • Nacos
  • Zookeeper
  • Sentinel
  • Seata
  • Gateway
  • Go基础
  • Gin
  • SQL数据库

    • MySQL
    • Oracle
  • NoSQL数据库

    • Redis
    • MongoDB
    • ElasticSearch
  • 消息中间件

    • RabbitMQ
    • RocketMQ
    • Kafka
    • ActiveMQ
    • MQTT
    • NATS
  • 网关中间件

    • Nginx
  • Linux
  • Docker
  • Git
  • K8s
  • Solidity
  • Java
  • 计算机网络
  • 操作系统
GitHub (opens new window)
npm

(进入注册为作者充电)

  • JVM基础

    • 初识JVM
    • 字节码文件详解
    • 运行时数据区
    • 垃圾回收
  • JVM实战

    • 内存调优
    • GC调优
    • 性能调优
  • JVM高级

    • GraalVM
    • 新一代的GC
    • 揭秘Java工具
  • JVM原理

    • 栈上的数据存储
    • 对象在堆上是如何存储的?
    • 方法调用的原理
    • 异常捕获的原理
    • JIT即时编译器
    • 垃圾回收器原理
  • JVM面试

    • 什么是JVM?
    • 了解过字节码文件的组成吗?
    • 说一下运行时数据区
    • 哪些区域会出现内存溢出,会有什么现象?
    • JVM在JDK6-8之间在内存区域上有什么不同
    • 类的生命周期
    • 什么是类加载器?
    • 什么是双亲委派机制
    • 如何打破双亲委派机制
    • Tomcat的自定义类加载器
    • 如何判断堆上的对象没有被引用??
    • JVM 中都有哪些引用类型?
    • ThreadLocal中为什么要使用弱引用?
    • 有哪些常见的垃圾回收算法?
    • 有哪些常用的垃圾回收器?
      • Serial垃圾回收器 + SerialOld垃圾回收器
      • Parallel Scavenge垃圾回收器 + Parallel Old垃圾回收器
      • 年轻代-ParNew垃圾回收器
      • 老年代- CMS(Concurrent Mark Sweep)垃圾回收器
      • G1 – Garbage First 垃圾回收器
      • 什么是Shenandoah?
      • 什么是ZGC?
      • 垃圾回收器的技术演进
      • 总结:
    • 如何解决内存泄漏问题?
    • 常见的JVM参数?
  • 《JVM》笔记
  • JVM面试
Salmon
2024-03-12
目录

有哪些常用的垃圾回收器?

  • 关联课程内容

    • 基础篇-垃圾回收器1
    • 基础篇-垃圾回收器2
    • 基础篇-垃圾回收器3
    • 基础篇-g1垃圾回收器
    • 实战篇-垃圾回收器的选择
    • 高级篇-ShenandoahGC
    • 高级篇-ZG
  • 回答路径

    • Serial垃圾回收器 + SerialOld垃圾回收器
    • ParNew + CMS
    • PS + PO
    • G1
    • Shenandoah 和 ZGC

垃圾回收器是垃圾回收算法的具体实现。

由于垃圾回收器分为年轻代和老年代,除了G1之外其他垃圾回收器必须成对组合进行使用。

具体的关系图如下:

img

# Serial垃圾回收器 + SerialOld垃圾回收器

Serial是是一种单线程串行回收年轻代的垃圾回收器。

-XX:+UseSerialGC 新生代、老年代都使用串行回收器。

img

回收年代和算法

  • 年轻代复制算法
  • 老年代标记-整理算法

优点

单CPU处理器下吞吐量非常出色

缺点

多CPU下吞吐量不如其他垃圾回收器,堆如果偏大会让用户线程处于长时间的等待

适用场景

Java编写的客户端程序或者硬件配置有限的场景

# Parallel Scavenge垃圾回收器 + Parallel Old垃圾回收器

PS+PO是JDK8默认的垃圾回收器,多线程并行回收,关注的是系统的吞吐量。具备自动调整堆内存大小的特点。

img

回收年代和算法

  • 年轻代复制算法
  • 老年代标记-整理算法

优点

吞吐量高,而且手动可控。为了提高吞吐量,虚拟机会动态调整堆的参数

缺点

不能保证单次的停顿时间

适用场景

后台任务,不需要与用户交互,并且容易产生大量的对象

比如:大数据的处理,大文件导出

# 年轻代-ParNew垃圾回收器

ParNew垃圾回收器本质上是对Serial在多CPU下的优化,使用多线程进行垃圾回收

-XX:+UseParNewGC 新生代使用ParNew回收器,老年代使用串行回收器

img

回收年代和算法

  • 年轻代
  • 复制算法

优点

多CPU处理器下停顿时间较短

缺点

吞吐量和停顿时间不如G1,所以在JDK9之后不建议使用

适用场景

JDK8及之前的版本中,与CMS老年代垃圾回收器搭配使用

# 老年代- CMS(Concurrent Mark Sweep)垃圾回收器

CMS垃圾回收器关注的是系统的暂停时间,允许用户线程和垃圾回收线程在某些步骤中同时执行,减少了用户线程的等待时间。

参数:-XX:+UseConcMarkSweepGC

img

回收年代和算法

  • 老年代
  • 标记清除算法

优点

系统由于垃圾回收出现的停顿时间较短,用户体验好

缺点

1、内存碎片问题

2、退化问题

3、浮动垃圾问题

适用场景

大型的互联网系统中用户请求数据量大、频率高的场景

比如订单接口、商品接口等

CMS垃圾回收器存在的问题

1、CMS使用了标记-清除算法,在垃圾收集结束之后会出现大量的内存碎片,CMS会在Full GC时进行碎片的整理。这样会导致用户线程暂停,可以使用-XX:CMSFullGCsBeforeCompaction=N 参数(默认0)调整N次Full GC之后再整理。

2.、无法处理在并发清理过程中产生的“浮动垃圾”,不能做到完全的垃圾回收。

3、如果老年代内存不足无法分配对象,CMS就会退化成Serial Old单线程回收老年代。

4、并发阶段会影响用户线程执行的性能

# G1 – Garbage First 垃圾回收器

参数1: -XX:+UseG1GC 打开G1的开关,JDK9之后默认不需要打开

参数2:-XX:MaxGCPauseMillis=毫秒值

最大暂停的时间

img

回收年代和算法

  • 年轻代+老年代
  • 复制算法

优点

对比较大的堆如超过6G的堆回收时,延迟可控

不会产生内存碎片

并发标记的SATB算法效率高

缺点

JDK8之前还不够成熟

适用场景

JDK8最新版本、JDK9之后建议默认使用

# 什么是Shenandoah?

Shenandoah 是由Red Hat开发的一款低延迟的垃圾收集器,Shenandoah 并发执行大部分 GC 工作,包括并发的整理,堆大小对STW的时间基本没有影响。

img

# 什么是ZGC?

ZGC 是一种可扩展的低延迟垃圾回收器。ZGC 在垃圾回收过程中,STW的时间不会超过一毫秒,适合需要低延迟的应用。支持几百兆到16TB 的堆大小,堆大小对STW的时间基本没有影响。

img

# 垃圾回收器的技术演进

img

# 总结:

垃圾回收器的组合关系虽然很多,但是针对几个特定的版本,比较好的组合选择如下:

JDK8及之前:

ParNew + CMS(关注暂停时间)、Parallel Scavenge + Parallel Old (关注吞吐量)、 G1(JDK8之前不建议,较大堆并且关注暂停时间)

JDK9之后:

G1(默认)

从JDK9之后,由于G1日趋成熟,JDK默认的垃圾回收器已经修改为G1,所以强烈建议在生产环境上使用G1。

如果对低延迟有较高的要求,可以使用Shenandoah或者ZGC。

上次更新: 2025/03/09, 18:29:07
有哪些常见的垃圾回收算法?
如何解决内存泄漏问题?

← 有哪些常见的垃圾回收算法? 如何解决内存泄漏问题?→

Theme by Vdoing | Copyright © 2022-2025 Salmon's Blog
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式