JVM之历代垃圾收集器讲解

  • 总览
    • 分类
    • 并行和并发
  • 年轻代垃圾回收器
    • Serial收集器
      • 特点
      • 优点
      • 缺点
    • PartNew收集器
      • 特点:
    • Parallel Scavenge收集器
    • 特点
  • 老年代垃圾回收器
    • Serial Old收集器
    • Parallel Old收集器
      • 组合
    • CMS收集器
    • 特点
    • 工作流程
      • 1.初始标记
      • 2.并发标记
      • 3.重新标记
      • 4.并发清除
  • G1 收集器
    • 特点
      • 实现
      • 优点
      • 缺点
      • 工作流程
  • 总结

总览

分类

一,采用分代理念的垃圾回收器:

1.年轻代:
Serial
PartNew
Parallel Scavenge

2.老年代:

CMS
Serial Old(MSC)
Parallel Old

二,不采用分代理念的垃圾回收器:

G1
ZGC
Shenandoah

可搭配使用的各个收集器之间关系图:

并行和并发

很多人经常把这两个搞混,当然笔者刚开始的时候也是傻傻分不清楚。其实只要记住并行说的是GC 线程之间的关系,而并发说的是GC和用户线程之间的关系。

并行:同一时间有多条这样的线程在协同工作,但是此时用户线程时等待状态

并发:同一时间GC和用户线程可以一起工作一起运行。因此程序依然能够响应用户线程的操作但是由于GC线程也占用了一部分系统资源,所以此时的用户线程处理的效率会下降

年轻代垃圾回收器

Serial收集器

特点

垃圾回收时需要STW,整个STW需要停止掉所有的用户线程来保证回收过程中引用关系不会发生变化。

但是并不是说垃圾回收的时候只会启用一个回收线程,更准确的描述应该是同一时间只允许一个垃圾回收线程工作,也就是不支持并行工作,多个GC线程之间串行工作。

优点

1.对于内存资源受限的机器来说比较友好:

由于回收时停止掉了所有的用户线程,因此他不必维护那些:用户线程和GC线程同时运行的时候在回收过程中为了保证引用关系发生变化的额外内存开销;比如上一篇文章说到的原始快照和增量更新。

2.而且由于GC线程不是并行的,所以没有线程之间的交互;对于处理器内核少(线程少)的机器来说,

第一点也就是线程串行执行一个线程完了之后才能执行下一个线程,而对于并行的来说其实本质上还是串行只不过各个线程间可以自由来回切换,所以需要对切换前后的资源进行额外的保存等等因此并发涉及到的这部分线程交互开销对于该款串行执行的GC线程时没有的

图示:

缺点

但是缺点也很明显:回收过程中停止掉所有用户线程,对用户肯定是不能容忍的

PartNew收集器

特点:

该款垃圾收集器和刚才讲的第一个Serial收集器其实最大的不同就是GC Thread可以并行的区别。
注意是并行,之后讲解的CMS才是可以实现GC Thread并发的收集器。

Parallel Scavenge收集器

特点

该款垃圾收集器同样和PartNew收集器一样,并行GC线程。只不过该款收集器重点是倾向于吞吐量

老年代垃圾回收器

Serial Old收集器

区别于Serial回收器只是回收算法的不同

Parallel Old收集器

Parallel Scavenge收集器的老年代版本,支持多线程并发收集。

组合

吞吐量优先垃圾回收器组合:

新生代采用Parallel Scavenge收集器,老年代采用Parallel Old收集器

CMS收集器

全称:Concurrent Mark Sweep

特点

1.采用标记-清除算法实现
2.和Parallel 系列的收集器注重点不同:

Parallel 注重吞吐量CMS注重STW的停顿时间

工作流程

1.初始标记

CMS inital mark

标记GC Roots直接关联的对象
需要STW

2.并发标记

CMS concurrent mark

根据上一步和GC Roots直接关联的对象进行遍历整个堆里面的对象图并进行标记,由于是并发的所以并不需要停顿用户线程,但是比较耗时因为遍历整个对象图。

3.重新标记

CMS remark

在并发标记期间由于和用户线程时并发的,所以这段期间用户线程可能更新了引用,所以需要进行一次修正(详见上一篇文章中讲到的增量更新
需要STW,STW停顿时间比初始标记时间长,但是并没有并发标记运行时间长

4.并发清除

清除删掉被标记为垃圾的对象,由于采用的是标记-清除算法,所以并不需要移动存活对象因此是可以并发的。(当内存碎片严重到不足以分配对象时其实还是需要进行标记-整理算法的,这个时候就会提前触发FullGC。)

注意:在并发阶段产生的**“浮动垃圾”**(并发时用户线程产生的垃圾),需要等到下一次垃圾回收才能进行清理;而且并发的时候需要预留一部分内存空间供用户线程使用,所以不能等到老年代完全用完在进行清理。JDK5的默认设置是当老年代使用了65%的空间就会触发GC。

G1 收集器

特点

思维方式的重大转变:

G1之前的收集器都是分代收集的思想,根据不同的代采用不同的GC:新生代(Minor GC),老年代(Major GC),整个JAVA堆(Full GC)。

但是GC是根据哪块内存中垃圾数量多回收效益最大来区分的,面向的是堆内存中的任意一块内存来组成回收集(Collection Set)进行回收。

实现

基于Region的堆内存布局来实现该回收过程。不再以固定大小及固定数量来划分分代区域,而是把连续的堆内存区域进行划分为各自独立大小相等的区域(Region),每一个Region都可以根据需要扮演新生代中的Enen空间,Survivor空间,或者老年代。收集器根据扮演不同角色的Region采用不同策略去处理。

Region中有一类特殊的Humongous区域,专门用来存储大对象。

G1认为一个对象的大小超过了一个Region空间的一半就认为该对象是大对象,如果超过了整个Region空间的超大对象将会被存放在连续的Humongous Region中,因此该区域一般会被作为老年代看待。

优点

1.建立可预测的停顿时间模型
由于采用的是Region,因此回收单元作为Region即每次回收都是Region大小的整数倍。

G1会跟踪Region区域里面垃圾堆,计算出价值(回收所获得的空间大小以及回收所需时间的经验值),接着在后台维护一个优先级列表,根据用户设置的允许停顿时间来进行回收价值最大的Region区域。也就是“Garbage First”
的由来。

2.内存碎片
整体上采用的是标记-整理,但是在两个Region中实际上还是采用的复制算法,所以不会出现内存碎片问题。

缺点

1.浪费额外内存来维护收集器工作

跨代引用避免全堆扫描之前说过是采用记忆集的方式来解决,在G1中也一样。
每个Region中都有自己的记忆集但是在G1中每个Region除了需要记录别的Region指向自己的指针,还需要标记这些指针分别在哪些卡页范围内。其实本质上说是哈希表,Key是别的Region的起始地址,Value是一个集合存储的元素是卡表的索引号。
因此实现起来比原有的记忆集要复杂,而且Region的数量比之前的分代数量要多得多,所以记忆集的维护占用了更高的内存

G1至少要耗费大约相当于JAVA堆容量的10%到20%来存储维持收集器正常工作

2.不仅用到写后屏障还用到了写前屏障

上一小点中已经讲到维护卡表是需要进行添加写后屏障来完成更新卡表的操作的,但是G1还用到了写前屏障:由于使用的是原始快照来保证可以进行并发标记的基础,对比与增量更新来说虽然能够减少最终标记的停顿时间,但是相比于收集器,这款收集器不仅采用了写前屏障也采用了写后屏障导致最终的效率降低

工作流程

与之前不同的是最后一处,这个步骤需要进行更新Region的统计数据,对所有的Region的回收价值和成本进行排序,然后根据用户设定的期望停顿时间进行决定选择哪几个Region构成回收集,然后将一部分的Region中存活对象复制到另外一个空的Region空间中,随后进行清理掉整个旧的Region空间。是不是复制算法(针对与Region来说),因为涉及对象移动,所以需要暂停用户线程

总结

到此,如果读者之前阅读过笔者之前的关于垃圾回收器讲解的文章,其实已经对现在大多数垃圾回收器机制和实现原理了解的差不多了,读者有兴趣可以自行去看Shenandoah收集器和ZGC收集器,本文不在叙述,主要确实文章内容优点太长了哈哈。
后面的文章将不在分析垃圾回收器的知识,但是还是会更新关于JVM的文章。

JVM之历代垃圾收集器详解相关推荐

  1. GC之7大垃圾收集器详解(下)

    GC之7大垃圾收集器详解 目录 GC之CMS收集器 GC之SerialOld收集器 GC之如何选择垃圾收集器 GC之G1收集器 第一部分请参见: GC之7大垃圾收集器详解(上) 6. GC之CMS收集 ...

  2. GC之7大垃圾收集器详解(上)

    GC之7大垃圾收集器详解 目录 GC之7大垃圾收集器概述 GC之Serial收集器 GC之ParNew收集器 GC之Parallel收集器 GC之ParallelOld收集器 GC之CMS收集器 GC ...

  3. G1 垃圾收集器详解

    Garbage First(简称G1)收集器开创了收集器面向局部收集的设计思路和基于Region的内存布局形式.它是一款专门针对于拥有多核处理器和大内存的机器的收集器,在满足了GC响应时间的延迟可控的 ...

  4. 深入理解Java虚拟机——JVM垃圾回收机制和垃圾收集器详解

    一:概述 说起垃圾回收(Garbage Collection,GC),很多人就会自然而然地把它和Java联系起来.在Java中,程序员不需要去关心内存动态分配和垃圾回收的问题,顾名思义,垃圾回收就是释 ...

  5. JVM垃圾收集器详解 CMS、G1、Shenandoah、ZGC

    上一篇我们讲解了一些垃圾回收的理论和一些基础的算法和思想,这一篇主要是jvm从古至今垃圾收集器的实现. 各垃圾回收器 注:有连线的代表他们可以互相配合使用. Serial和Serial Old收集器 ...

  6. JVM之垃圾收集算法和垃圾收集器详解

    这篇文章相比上一篇记录性的,多了不少我自己的理解,花费了很大的功夫整理,如果有时间和精力建议好好看一看深入理解JVM这本书. 也建议熟读背诵. JVM-垃圾收集器和内存分配策略 程序计数器.虚拟机栈. ...

  7. CMS垃圾收集器详解

    概述 CMS垃圾收集器是一款优秀的老年代并发垃圾收集器,通过与用户线程并发执行的方式减少GC停顿的时间.本文主要聊一下CMS设计到的相关的数据结构.具体的执行过程.运行中会出现的异常情况. 在CMS之 ...

  8. (七)Java垃圾收集器详解

    面试官问:Java垃圾收集器了解过多少,说一下 JVM 有哪些垃圾回收器?这些问题在你面试高级Java的时候经常会问到.本篇文章结合着[深入理解Java虚拟机]一书当中整理了本篇博客. 如果想要对收集 ...

  9. CMS、G1垃圾收集器详解

    CMS垃圾收集器 基本上只能用在老年代,很长一段时间是ParNew(新生代)搭配CMS(老年代)来使用的. 收集过程大概会分为如下4个过程: 1.初始标记: 暂停所有的其他线程,并记录下gc root ...

最新文章

  1. 面试官:说说Innodb中LRU怎么做的?
  2. php直接修改excel,php如何修改excel
  3. ExtJS4.x动态加载js文件
  4. java mvc 导入_Java SpringMVC文件导入和导出
  5. python的格式化输出学号_安利三个关于Python字符串格式化进阶知识
  6. 【Nginx探究系列二】Nginx配置篇之客户Nginx白名单访问配置
  7. The content of the adapter has changed but ListView did not receive a notification
  8. 2021-07-13 CNN池化理解学习
  9. c语言的程序的基本示例
  10. 最新版 银图/网银/MOMO模拟按键/Photoshop图像处理
  11. bp神经网络的训练过程,一文搞定bp神经网络
  12. CVE-2022-21999 Windows Print Spooler(打印服务)特权提升漏洞
  13. 感性电路电流计算_三相电的电功率的计算公式_200KW三相四线制线路,需要多少A电源空开?...
  14. java地铁线路规划_地铁路线规划系统
  15. 四个Channel的讲解
  16. RSE2022/云检测:A hybrid generative adversarial network for weakly-supervised cloud detection 多光谱图像弱监督云检
  17. 设计模式及其应用场景
  18. 面向对象开发期末复习概述(四)
  19. 安卓软件远程连接ConnectBot v1.8.6
  20. 美多商城项目发送短信优化

热门文章

  1. JavaScript前端实现压缩图片功能
  2. [附源码]Java计算机毕业设计SSM爱心宠物中心管理系统
  3. qlist 对结构体排序
  4. 二叉树中序非递归遍历
  5. python歌词解析_python 将歌词解析封装成类,要求:提供一个方法(根据时间返回歌-站长资讯中心...
  6. Word编号经常感觉用不习惯?看看这4个编号技巧吧,省事又好用
  7. Latex 自定义算法编号
  8. ME525软件测试自学,电脑通过WIFI连接摩托罗拉(defy) ME525上网的方法
  9. 动态SQL与静态SQL
  10. 操作系统-在Linux和windows 下cpu过高和风扇转不停的原因