垃圾回收器有哪些?是一个高频的面试题,那本文就详细来解答这个问题。

因为不同的厂商(IBM、Oracle),实现的垃圾回收器各不相同,而本文要讨论的是 Oracle 的 HotSpot 虚拟机所使用的垃圾回收器。

常用垃圾回收器,如下图所示:

  • 新生代回收器:Serial、ParNew、Parallel Scavenge

  • 老年代回收器:Serial Old、Parallel Old、CMS

  • 整堆回收器:G1

其中相互连线的垃圾回收器,表示可以相互搭配使用。

新生代 And 老生代

目前常用的商用垃圾收集器都使用的是分代垃圾回收方式。

分代垃圾回收器把内存分为:新生代(Young Generation)和老生代(Tenured Generation),如下图所示:

(图片来自fancydeepin)

默认情况下,新生代和老生代的内存比例是 1:2,该值可以通过 -XX:NewRatio 来设定。

新生代(Young Generation)

程序中的大部分对象都符合“朝生夕死”的特性,所以绝大数新创建的对象都会存放在新生代,除非是大对象会直接进入老生代。新生代采用的是复制算法,这样可以更高效的回收内存空间。

新生代有细分为:Eden、Form Survivor、To Survivor 三个区域,默认的比例是 8:1:1,可以通过 -XX:SurvivorRatio 来设定。

新生代垃圾回收的执行过程:

1、Eden 区 + From Survivor 区存活着的对象复制到 To Survivor 区;

2、清空 Eden 和 From Survivor 分区;

3、From Survivor 和 To Survivor 分区交换(From 变 To,To 变 From)。

老生代(Tenured Generation)

老生代垃圾回收的频率比新生代低,存放的主要对象是:

1、新生代对象经过 N 次 GC 晋升到老年代。

可以通过设置 -XX:MaxTenuringThreshold=5 来设置,默认值是 15 次。

2、大对象直接存储到老生代。

所谓的“大对象”指的是需要连续存储空间的对象,比如:数组。

当大对象在新生代存储不下的时候,就需要分配担保机制,把当前新生代的所有对象复制到老年代中,因为分配担保机制需要涉及大量的复制,会导致性能问题,所有最好的方案是直接把大对象存储到老生代中。

通过参数 -xx:PretrnureSizeThreshold 来设定大对象的值。

注意:该参数只有 Serial 和 ParNew 垃圾回收器有效。

Serial

Serial 最早的垃圾回收器,JDK 1.3.1 之前新生代唯一的垃圾回收器,使用的是单线程串行回收方式,在单 CPU 环境下性能较好,因为单线程执行不存在线程切换。

线程类型: 单线程

使用算法: 复制算法

指定收集器: -XX:+UseSerialGC

Serial Old

Serial 收集器的老年代版本,同样也是单线程的。它有一个实用的用途作为CMS收集器的备选预案,后面介绍CMS的时候会详细介绍。

线程类型: 单线程

使用算法: 标记-整理

指定收集器: -XX:+UseSerialGC

ParNew

ParNew 其实就是 Serial 的多线程版本,可以和 Serial 共用很多控制参数,比如:-XX:SurvivorRatio , ParNew 可以和 CMS 配合使用。

(注:图片来源于零壹技术栈)

线程类型: 多线程

使用算法: 复制

指定收集器: -XX:+UseParNewGC

Parallel Scavenge

Parallel 和 ParNew 收集器类似,也是多线程的,但 Parallel 是吞吐量优先的收集器,GC停顿时间的缩短是以吞吐量为代价的,比如收集 100MB 的内存,需要 10S 的时间,CMS 则会缩短为 7S 收集 50 MB 的内存,这样停顿的时间确实缩少了,但收集的频率变大了,吞吐量就变小了。

线程类型: 多线程

使用算法: 复制

指定收集器: -XX:+UseParallelGC

Parallel Old

Parallel Old 是 Parallel 的老生代版本,同样是吞吐量优先的收集器。

线程类型: 多线程

使用算法: 标记-整理

指定收集器: -XX:+UseParallelOldGC

CMS

CMS(Concurrent Mark Sweep)一种以获得最短停顿时间为目标的收集器,非常适用B/S系统。

使用 Serial Old 整理内存。

CMS 运行过程:

(注:图片来源于零壹技术栈)

1、初始标记

标记 GC Roots 直接关联的对象,需要 Stop The World 。

2、并发标记

从 GC Roots 开始对堆进行可达性分析,找出活对象。

3、重新标记

重新标记阶段为了修正并发期间由于用户进行运作导致的标记变动的那一部分对象的标记记录。这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短,也需要 Stop The World 。

4、并发清除

除垃圾对象。

CMS 缺点:

1、对 CPU 资源要求敏感。

CMS 回收器过分依赖于多线程环境,默认情况下,开启的线程数为(CPU 的数量 + 3)/ 4,当 CPU 数量少于 4 个时,CMS 对用户本身的操作的影响将会很大,因为要分出一半的运算能力去执行回收器线程。

2、CMS无法清除浮动垃圾。

浮动垃圾指的是CMS清除垃圾的时候,还有用户线程产生新的垃圾,这部分未被标记的垃圾叫做“浮动垃圾”,只能在下次 GC 的时候进行清除。

3、CMS 垃圾回收会产生大量空间碎片。

CMS 使用的是标记-清除算法,所有在垃圾回收的时候回产生大量的空间碎片。

注意:CMS 收集器中,当老生代中的内存使用超过一定的比例时,系统将会进行垃圾回收;当剩余内存不能满足程序运行要求时,系统将会出现 Concurrent Mode Failure,临时采用 Serial Old 算法进行清除,此时的性能将会降低。

线程类型: 多线程

使用算法: 标记-清除

指定收集器: -XX:+UseConcMarkSweepGC

G1

G1 GC 这是一种兼顾吞吐量和停顿时间的 GC 实现,是 JDK 9 以后的默认 GC 选项。G1 可以直观的设定停顿时间的目标,相比于 CMS GC,G1 未必能做到 CMS 在最好情况下的延时停顿,但是最差情况要好很多。

G1 GC 仍然存在着年代的概念,但是其内存结构并不是简单的条带式划分,而是类似棋盘的一个个 region。Region 之间是复制算法,但整体上实际可看作是标记 - 整理(Mark-Compact)算法,可以有效地避免内存碎片,尤其是当 Java 堆非常大的时候,G1 的优势更加明显。

G1 吞吐量和停顿表现都非常不错,并且仍然在不断地完善,与此同时 CMS 已经在 JDK 9 中被标记为废弃(deprecated),所以 G1 GC 值得深入掌握。

G1 运行过程:

1、初始标记

标记 GC Roots 直接关联的对象,需要 Stop The World 。

2、并发标记

从 GC Roots 开始对堆进行可达性分析,找出活对象。

3、重新标记

重新标记阶段为了修正并发期间由于用户进行运作导致的标记变动的那一部分对象的标记记录。这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短,也需要 Stop The World 。

4、筛选回收

首先对各个 Region 的回收价值和成本进行排序,根据用户所期望的 GC 停顿时间来制定回收计划。这个阶段可以与用户程序一起并发执行,但是因为只回收一部分 Region,时间是用户可控制的。

线程类型: 多线程

使用算法: 复制、标记-整理

指定收集器: -XX:+UseG1GC(JDK 7u4 版本后可用)

垃圾回收器都有哪些?相关推荐

  1. 经典面试题 | 讲一下垃圾回收器都有哪些?

    垃圾回收器有哪些?是一个高频的面试题,那本文就详细来解答这个问题. 因为不同的厂商(IBM.Oracle),实现的垃圾回收器各不相同,而本文要讨论的是 Oracle 的 HotSpot 虚拟机所使用的 ...

  2. V8 JavaScript引擎研究(三)垃圾回收器的实现

    V8垃圾回收机制简介 V8垃圾回收器的实现,是V8高效的一个非常重要的原因. V8在运行时自动回收不再需要使用的对象内存,也即是垃圾回收. V8使用了全暂停式(stop-the-world).分代式( ...

  3. python 垃圾回收器_Python 垃圾回收机制详细

    引用计数 Python语言默认采用的垃圾收集机制是『引用计数法 Reference Counting』,该算法最早George E. Collins在1960的时候首次提出,50年后的今天,该算法依然 ...

  4. 【拥抱大厂系列】几个面试官常问的垃圾回收器,下次面试就拿这篇文章怼回去!

    点个赞,看一看,好习惯!本文 GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了3个月总结的一线大厂Java面试总结,本人已拿腾 ...

  5. 几个面试官常问的垃圾回收器,下次面试就拿这篇文章怼回去!

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:牛人 20000 字的 Spring Cloud 总结,太硬核了~ 先瞎比比一下,上一篇文章已经过去2个多月了, ...

  6. 前沿实践:垃圾回收器是如何演进的?

    简介:上一篇<底层原理:垃圾回收算法是如何设计的?>介绍了垃圾回收的基本原理,以及若干种基本算法和优化算法,这部分内容属于垃圾回收的方法论.下面将结合业界目前垃圾回收器的发展方向,介绍几种 ...

  7. java不同垃圾回收器_细述 Java垃圾回收机制→Types of Java Garbage Collectors

    本文非原创,翻译自Types of Java Garbage Collectors 在Java中为对象分配和释放内存空间都是由垃圾回收线程自动执行完成的.和C语言不一样的是Java程序员不需要手动写垃 ...

  8. 垃圾回收算法_Java 垃圾回收算法与几种垃圾回收器

    一.如何确定某个对象是"垃圾"? 目前主流垃圾回收器都采用的是可达性分析算法来判断对象是否已经存活,不使用引用计数算法判断对象时候存活的原因在于该算法很难解决相互引用的问题.如何确 ...

  9. jdk8默认垃圾回收器_JVM系列之经典垃圾回收器(上篇)

    封面图 1.前言 随着 JDK 的不断更新,垃圾回收器的效率也越来越高.每一次 JDK 的更新,必然会包含有垃圾回收器的更新,截止目前,在最新的 JDK14 版本中,最新的垃圾回收器为 ZGC. 从垃 ...

最新文章

  1. Spring Boot 2.0(七):Spring Boot 如何解决项目启动时初始化资源
  2. Linux中的SELinux与chcon以及Samba实现【转】
  3. linux查看告警日志,shell脚本,用于监视Linux中的消息日志(警告,错误和严重)...
  4. 华为端到端项目管理流程_【达睿原创】供应链端到端管理 – 看华为是怎么做的...
  5. RxSwift之UI控件UICollectionView扩展的使用
  6. oracle安装缺少,安装oracle11g R2 缺少依赖包
  7. java 扫描类_Java扫描指定包中所有类
  8. 用友元函数重载乘法,用成员函数重载除法
  9. PXE(preboot execute environment)
  10. 利用AWVS进行反制
  11. 卡巴斯基2009注册机[纯绿色版本]
  12. BankNext 微服务:案例研究
  13. image.getSubimage(x, y, width, height)函数解析
  14. jsp中的property
  15. Postgres-XL集群的搭建和测试详解
  16. 发光环绕文字特效怎么做?教程来了
  17. eclipse4.6安装tomcate插件 Eclipse4.6(neno)配置Tomcat插件的两种方式
  18. 什么是Apache Isis
  19. 电容实际等效模型(容抗、感抗、品质因数Q)
  20. 用Excel制作贪吃蛇

热门文章

  1. 【学习打卡03】可解释机器学习笔记之CAM类激活热力图
  2. CureApp高血压治疗App:2021 ESC大会发布在知名心血管期刊《欧洲心脏杂志》上发表的临床试验结果
  3. 智慧高校共享单车管理系统
  4. 基于双向LSTM卷积网络与注意力机制的自动睡眠分期模型
  5. Java集合框架篇-63-TreeSet集合练习题
  6. PE启动菜单修改工具 MsgDiyer(GfxMenu Message制作工具) V2.0.3官方版
  7. RK3568平台开发系列讲解(内核篇)挂载文件系统介绍
  8. 解决方法 android.view.AbsSavedState$1 cannot be cast to android.widget.CompoundButton$SavedState
  9. Matlab完整教程专栏完整目录
  10. java试题库管理系统源代码_Java试题库管理源代码