JVM从入门到入土之详解G1垃圾回收器

前言

文本已收录至个人GitHub仓库,欢迎Star:https://github.com/bin392328206/six-finger
种一棵树最好的时间是十年前,其次是如今
我知道不少人不玩qq了,可是怀旧一下,欢迎加入六脉神剑Java菜鸟学习群,群聊号码:549684836 鼓励你们在技术的路上写博客git

絮叨

Garbage First(G1)是垃圾收集领域的最新成果,同时也是HotSpot在JVM上力推的垃圾收集器,并赋予取代CMS的使命。若是使用Java 8/9,那么有很大可能但愿对G1收集器进行评估。本文详细首先对JVM其余的垃圾收集器进行总结,并与G1进行了简单的对比;而后经过G1的内存模型、G1的活动周期,对G1的工做机制进行了介绍;同时还在介绍过程当中,描述了可能须要引发注意的优化点。博主但愿经过本文,让有必定JVM基础的读者能尽快掌握G1的知识点。github

JVM GC收集器的回顾与比较

到JDK1.8为止的垃圾回收器图以下web

其实他们的一个迭代的过程是随着技术的演化进行的算法

串行收集器组合 Serial + Serial Old

开启选项:-XX:+SerialGC安全

串行收集器是最基本、发展时间最长、久经考验的垃圾收集器,也是client模式下的默认收集器配置。服务器

串行收集器采用单线程stop-the-world的方式进行收集。当内存不足时,串行GC设置停顿标识,待全部线程都进入安全点(Safepoint)时,应用线程暂停,串行GC开始工做,采用单线程方式回收空间并整理内存。单线程也意味着复杂度更低、占用内存更少,但同时也意味着不能有效利用多核优点。事实上,串行收集器特别适合堆内存不高、单核甚至双核CPU的场合。多线程

并行收集器组合 Parallel Scavenge + Parallel Old

开启选项:-XX:+UseParallelGC或-XX:+UseParallelOldGC(可互相激活)并发

并行收集器是以关注吞吐量为目标的垃圾收集器,也是server模式下的默认收集器配置,对吞吐量的关注主要体如今年轻代Parallel Scavenge收集器上。编辑器

并行收集器与串行收集器工做模式类似,都是stop-the-world方式,只是暂停时并行地进行垃圾收集。年轻代采用复制算法,老年代采用标记-整理,在回收的同时还会对内存进行压缩。关注吞吐量主要指年轻代的Parallel Scavenge收集器,经过两个目标参数-XX:MaxGCPauseMills和-XX:GCTimeRatio,调整新生代空间大小,来下降GC触发的频率。并行收集器适合对吞吐量要求远远高于延迟要求的场景,而且在知足最差延时的状况下,并行收集器将提供最佳的吞吐量。学习

并发标记清除收集器组合 ParNew + CMS + Serial Old

开启选项:-XX:+UseConcMarkSweepGC

并发标记清除(CMS)是以关注延迟为目标、十分优秀的垃圾回收算法,开启后,年轻代使用STW式的并行收集,老年代回收采用CMS进行垃圾回收,对延迟的关注也主要体如今老年代CMS上。

年轻代ParNew与并行收集器相似,而老年代CMS每一个收集周期都要经历:初始标记、并发标记、从新标记、并发清除。其中,初始标记以STW的方式标记全部的根对象;并发标记则同应用线程一块儿并行,标记出根对象的可达路径;在进行垃圾回收前,CMS再以一个STW进行从新标记,标记那些由mutator线程(指引发数据变化的线程,即应用线程)修改而可能错过的可达对象;最后获得的不可达对象将在并发清除阶段进行回收。值得注意的是,初始标记和从新标记都已优化为多线程执行。CMS很是适合堆内存大、CPU核数多的服务器端应用,也是G1出现以前大型应用的首选收集器。

可是CMS并不完美,它有如下缺点:

  1. 因为并发进行,CMS在收集与应用线程会同时会增长对堆内存的占用,也就是说,CMS必需要在老年代堆内存用尽以前完成垃圾回收,不然CMS回收失败时,将触发担保机制,串行老年代收集器将会以STW的方式进行一次GC,从而形成较大停顿时间;
  2. 标记清除算法没法整理空间碎片,老年代空间会随着应用时长被逐步耗尽,最后将不得不经过担保机制对堆内存进行压缩。CMS也提供了参数-XX:CMSFullGCsBeForeCompaction(默认0,即每次都进行内存整理)来指定多少次CMS收集以后,进行一次压缩的Full GC。

Garbage First (G1)

开启选项:-XX:+UseG1GC

以前介绍的几组垃圾收集器组合,都有几个共同点:

  • 年轻代、老年代是独立且连续的内存块;
  • 年轻代收集使用单eden、双survivor进行复制算法;
  • 老年代收集必须扫描整个老年代区域;
  • 都是以尽量少而快地执行GC为设计原则。

G1垃圾收集器也是以关注延迟为目标、服务器端应用的垃圾收集器,被HotSpot团队寄予取代CMS的使命,也是一个很是具备调优潜力的垃圾收集器。虽然G1也有相似CMS的收集动做:初始标记、并发标记、从新标记、清除、转移回收,而且也以一个串行收集器作担保机制,但单纯地以相似前三种的过程描述显得并非很稳当。事实上,G1收集与以上三组收集器有很大不一样:

  • G1的设计原则是"首先收集尽量多的垃圾(Garbage - First)"。所以,G1并不会等内存耗尽(串行、并行)或者快耗尽(CMS)的时候开始垃圾收集,而是在内部- 采用了启发式算法,在老年代找出具备高收集收益的分区进行收集。同时G1能够根据用户设置的暂停时- 间目标自动调全年轻代和总堆大小,暂停目标越短年轻代空间越小、总空间就越大;
  • G1采用内存分区(Region)的思路,将内存划分为一个个相等大小的内存分区,回收时则以分区为单位进- 行回收,存活的对象复制到另外一个空闲分区中。因为都是以相等大小的分区为单位进行操做,所以G1天- 然就是一种压缩方案(局部压缩);
  • G1虽然也是分代收集器,但整个内存分区不存在物理上的年轻代与老年代的区别,也不须要彻底独立的- survivor(to space)堆作复制准备。G1只有逻辑上的分代概念,或者说每一个分区均可能随G1的运行在不- 同代之间先后切换;
  • G1的收集都是STW的,但年轻代和老年代的收集界限比较模糊,采用了混合(mixed)收集的方式。即每次- 收集既可能只收集年轻代分区(年轻代收集),也可能在收集年轻代的同时,包含部分老年代分区(混合- 收集),这样即便堆内存很大时,也能够限制收集范围,从而下降停顿

G1的内存模型

分区概念

以下图所示:

分区

分区 Region

G1采用了分区(Region)的思路,将整个堆空间分红若干个大小相等的内存区域,每次分配对象空间将逐段地使用内存。所以,在堆的使用上,G1并不要求对象的存储必定是物理上连续的,只要逻辑上连续便可;每一个分区也不会肯定地为某个代服务,能够按需在年轻代和老年代之间切换。启动时能够经过参数-XX:G1HeapRegionSize=n可指定分区大小(1MB~32MB,且必须是2的幂),默认将整堆划分为2048个分区。

卡片

卡片 Card

在每一个分区内部又被分红了若干个大小为512 Byte卡片(Card),标识堆内存最小可用粒度全部分区的卡片将会记录在全局卡片表(Global Card Table)中,分配的对象会占用物理上连续的若干个卡片,当查找对分区内对象的引用时即可经过记录卡片来查找该引用对象(见RSet)。每次对内存的回收,都是对指定分区的卡片进行处理。

堆 Heap

G1一样能够经过-Xms/-Xmx来指定堆空间大小。当发生年轻代收集或混合收集时,经过计算GC与应用的耗费时间比,自动调整堆空间大小。若是GC频率过高,则经过增长堆尺寸,来减小GC频率,相应地GC占用的时间也随之下降;目标参数-XX:GCTimeRatio即为GC与应用的耗费时间比,G1默认为9,而CMS默认为99,由于CMS的设计原则是耗费在GC上的时间尽量的少。另外,当空间不足,如对象空间分配或转移失败时,G1会首先尝试增长堆空间,若是扩容失败,则发起担保的Full GC。Full GC后,堆尺寸计算结果也会调整堆空间。

分代模型

分代

分代 Generation

分代垃圾收集能够将关注点集中在最近被分配的对象上,而无需整堆扫描,避免长命对象的拷贝,同时独立收集有助于下降响应时间。虽然分区使得内存分配再也不要求紧凑的内存空间,但G1依然使用了分代的思想。与其余垃圾收集器相似,G1将内存在逻辑上划分为年轻代和老年代,其中年轻代又划分为Eden空间和Survivor空间。但年轻代空间并非固定不变的,当现有年轻代分区占满时,JVM会分配新的空闲分区加入到年轻代空间。

整个年轻代内存会在初始空间-XX:G1NewSizePercent(默认整堆5%)与最大空间-XX:G1MaxNewSizePercent(默认60%)之间动态变化,且由参数目标暂停时间-XX:MaxGCPauseMillis(默认200ms)、须要扩缩容的大小以及分区的已记忆集合(RSet)计算获得。固然,G1依然能够设置固定的年轻代大小(参数-XX:NewRatio、-Xmn),但同时暂停目标将失去意义。

结论

总的来讲,G1能够作到让你本身来设置垃圾回收对系统的影响,他本身经过把内存拆分为大量小Region,以及追踪每一个Region中能够回收的对象大小和预估时间,最后在垃圾回收的时候,尽可能把垃圾回收对系统形成的影响控制在你指定的范围内,同时在有限的时间内尽可能回收可能多的垃圾对象

结尾

其实这个也就是一个简单的的介绍,下面一篇咱们来讲说线上环境G1垃圾回收器的具体使用和参数设置

由于博主也是一个开发萌新 我也是一边学一边写 我有个目标就是一周 二到三篇 但愿能坚持个一年吧 但愿各位大佬多提意见,让我多学习,一块儿进步。

平常求赞

好了各位,以上就是这篇文章的所有内容了,能看到这里的人呀,都是真粉

创做不易,各位的支持和承认,就是我创做的最大动力,咱们下篇文章见

六脉神剑 | 文 【原创】若是本篇博客有任何错误,请批评指教,不胜感激 !

相关文章
相关标签/搜索