# JVM学习——G1垃圾回收器
把这个跨时代的垃圾回收器的笔记独立出来。
新生代:适用复制算法
老年代:适用标记清除、标记整理算法
二娃本来看G1的时候觉得比较枯燥,但是后来总结完之后告诉我说,一定要慢慢的学,不要跳过东西。之前不懂的在后面总结的时候就豁然开朗了。
G1从JDK9开始,已经成为默认垃圾收集器。
G1:Garbage First Collector
垃圾优先的收集器和其他收集器最明显的不通:
物理结构和形态和之前极为不同。比如对于堆的使用空间的划分。哪里用于老年代,哪里用于新生代等等。
垃圾收集器的存在的两个指标
鱼和熊掌可兼得
吞吐量
吞吐量关注的是在一个指定的时间内,最大化一个应用的工作量
TPS:在同一个小时内同一个事物(或者任务,请求)完成的次数
数据库一小时可以完成多少次查询。
对于关注吞吐量的系统来说,卡顿(STW)是可以接受的。
相应能力
指一个程序或者系统对请求能够及时相应。如
- 一个桌面UI
对于这类对相应能力敏感的场景,长时间的停顿是无法接受的。
G1的设计目标
G1就是为了解决这两种问题而存在的垃圾回收器。(设计目标)
满足短时间GC停顿的同时达到一个较高的吞吐量
使用JVM参数就可以启用G1垃圾回收器。
几乎不需要STW,但是还有的。 一般很多人喜欢拿G1和CMS比较。
GC停顿更加可控(和新的物理结构设计有很大的关系,堆的内存的划分方式和CMS不一样。不是按照新生代和老年代来划分堆内存的。)
浮动垃圾:在清除的过程中,还会有产生的垃圾。这些垃圾称为浮动垃圾。
G1的设计规划:是要替换掉CMS。
但是实际上,并不是为了替换而替换的。因为不同的业务系统对于不同的需求不一样。必须对响应能力要求比较高的情况下,有时候是不需要考虑吞吐量的,所以在选用的时候还是需要酌情考虑。
HotSpot虚拟机的主要构成
方法区:存储的类的元数据,全局性的信息等等
Heap:堆,存放对象
Java线程:
程序计数器:用来表示程序指令所持有的信息
Naive:本地内部线程
再往下:执行引擎:JIT Compiler 及时编译器,垃圾收集器
垃圾收集器堆内存划分和角色分派
传统的垃圾收集器堆结构(非G1的垃圾收集器)
年轻代:Eden,S0,S1。 复制算法。
Old Generation:老年代。
永久代:已经弃用。1.8 包括1.8 以后就没有了。 老年代是不会晋升永久代的。永久代存的是常量之类的东西。 (10年以上工作经验的 好多都会说错,说老年代晋升永久代)
G1收集器堆结构
描述:交织在一起,没有规律可言。
显然:命名策略没有发生变化,还是用的Eden、Survivor、Old Generation、作用还是原来的作用。
但是:物理内存的方式,发生了翻天覆地的变化,和传统的堆内存划分没什么关系。
G1:堆内存,就是一个区域,就是一个Heap。regions
对每个角色的数量并没有强制的限定,对每种内存的大小,可以动态变化。
G1最大的特点就是高效的执行回收,优先去执行那些大量对象可回收的区域(region)。
G1采用复制算法
G1只是特定的整理几个Region。并不是整理所有的Region。所以GC停顿时间会明显变少。
关于G1的一些重要概念
分区:G1是依附的重要概念。每一个区域的大小是一样的。但是角色会动态发生变化。但是在同一时刻,某一个分区只是属于单一的某一个代。
年轻代,幸存区,老年代这些概念还在,但是成为了逻辑上的概念。
G1名字由来:垃圾优先。 G1会优先回收垃圾对象特别多的分区。
G1:在新生代满的时候,对新生代进行回收。和传统的一致。
复制算法的优点
CSet:就是要被收集的区域的集合。统称为收集集合。
RSet:记录其他Region中对象的引用本Region中对象的关系。
价值在于:不需要扫描整个堆去找谁引用了当前分区中的对象。只需要扫描Rset即可。
上述内容摘自:知乎 R大, RednaxelaFX.
4个重要概念:
SATB
Region
CSet
RSet
官网解读
https://www.oracle.com/technetwork/tutorials/tutorials-1876574.html
三个跟性能有关的JVM组件。高亮了。调优的时候主要针对这三部分。
两种调优:1. 调整堆的大小 2. 选择合适的垃圾回收器。 3. 在新版本的JDK中,我们几乎不用动JIT。
关于:关注点响应能力和吞吐量 的解释原文。
关于G1存在的目的:是为了替换CMS。和G1的详细介绍。
我去,这些东西不是都在官网吗?
When performing garbage collections, G1 operates in a manner similar to the CMS collector. G1 performs a concurrent global marking phase to determine the liveness of objects throughout the heap. After the mark phase completes, G1 knows which regions are mostly empty. It collects in these regions first, which usually yields a large amount of free space. This is why this method of garbage collection is called Garbage-First. As the name suggests, G1 concentrates its collection and compaction activity on the areas of the heap that are likely to be full of reclaimable objects, that is, garbage. G1 uses a pause prediction model to meet a user-defined pause time target and selects the number of regions to collect based on the specified pause time target.
The regions identified by G1 as ripe for reclamation are garbage collected using evacuation. G1 copies objects from one or more regions of the heap to a single region on the heap, and in the process both compacts and frees up memory. This evacuation is performed in parallel on multi-processors, to decrease pause times and increase throughput. Thus, with each garbage collection, G1 continuously works to reduce fragmentation, working within the user defined pause times. This is beyond the capability of both the previous methods. CMS (Concurrent Mark Sweep ) garbage collector does not do compaction. ParallelOld garbage collection performs only whole-heap compaction, which results in considerable pause times.
It is important to note that G1 is not a real-time collector. It meets the set pause time target with high probability but not absolute certainty. Based on data from previous collections, G1 does an estimate of how many regions can be collected within the user specified target time. Thus, the collector has a reasonably accurate model of the cost of collecting the regions, and it uses this model to determine which and how many regions to collect while staying within the pause time target.
Note: G1 has both concurrent (runs along with application threads, e.g., refinement, marking, cleanup) and parallel (multi-threaded, e.g., stop the world) phases. Full garbage collections are still single threaded, but if tuned properly your applications should avoid full GCs.
RSet和CSet的概念
G1收集器的阶段:
和CMS阶段执行内容不同的阶段。
G1总结:
有问题,就查询官网。
G1 深度理论讲解
Young GC和 Mix GC
Eden空间满的时候,收集新生代。使用G1收集器。
CSet
RSet涉及两个概念:points-into 和 points-out
SATB三色算法:增量式的标记算法。:沿着某一个起点,逐步的深入追踪。这就叫增量式。
我们不能将本来不是垃圾的对象当成垃圾来回收的,这种情况百分百是不能出现的。
把本来是垃圾的对象,认为不是垃圾。这种情况是允许的。称为浮动垃圾。
G1相对于CMS的优势
- 压缩空间的优势: CMS-标记清除算法,内存碎片多。 G1用的是拷贝算法,直接清除原空间
- Region分区,避免内存碎片问题
- Eden,Survivor,Old区不固定。是因为,G1没有显示固定设置每个代的空间大小。只是要求每个分区的大小是一样的就行。哪个区域不够开辟哪个空间
- G1可以通过设置预测模型,设置运行时间:指定的预判收集时间,显示的控制用户指定的收集时间
- G1采用的是内存拷贝的方法,直接清空释放空间。
- G1能够在年轻代使用。CMS只使用与老年代。
G1的使用场景
对于G1的收集,两种模式:对于年轻代的收集成为Young GC。 Mixed GC对于老年代和年轻代,都能够回收。
全局并发标记:
- young GC
- 并发阶段
- 混合模式
- Full GC
Young GC触发时间:
那么 什么时候触发Mixed GC?
G1HeapWasterPercent:参数
G1MixedGCLiveThresholdPercent:参数
G1MixedGCCOuntTarget:参数
G1OldSetRegionThresholdPercent:参数
G1 GC其他参数
其中:humongous为超大空间
无论是新生代还是老年代,都是复制算法。
巨大对象:存放在humongous区域。如果一个H区域放不下,会寻找连续的H分区来存储。
三色标记算法:黑白灰
三色标记算法为了解决并行标记出问题的情况。(漏标-本来不是垃圾的对象没有标记)(误标-本来是垃圾的没有标记)
并发标记采用的算法:三色标记算法。描述:追踪式(从根部追踪)。
但凡被标记对象,都不是垃圾,都不应该没回收掉
黑色:根对象,GCRoot,起源/ 该对象或者子对象都被扫描过了,也是黑色。
灰色:还没标记完,扫描当中
白色:还未被标记。扫描完成之后,白色对象就是不可达的对象,即垃圾对象。
变黑:是因为 不再引用其他的任何对象了,自身也扫描完了。
垃圾回收的漏标问题是如何产生的呢?如下状态
如果A.c = C。 B.c = null. 变成了这个样子。
这时候的问题就是:C对象已经被漏掉了。要被回收掉了。显然这是不合理的。这就是漏标现象。
SATB来合理的解决漏标的问题
变成非白色的:变成非白色之后就不会被垃圾回收掉了。就算真的没用了,也没事。但是就是不能被误删除。
新生代用分区,并不是为了提升效率。只是为了适合能够控制大小
SATB详解
隐式标记:默认灰色。找到新分配的对象
完整标记的流程
手动通过用户设置为null的,标记灰色
这里的停顿时间,并不是越短越好。因为:时间短,收集的垃圾就少。
G1的最佳实战
-
不断调优暂停时间指标:
-XX:MaxGCPauseMillis=x
暂停时间不能太短:如果太短就会导致出现G1跟不上垃圾产生的速度。最终退化成FUll GC。
-
不要设置新生代和老年代的大小
G1有自动调大小的功能
-
关注Evacuation Failure
G1 系统性回顾
通过上面的初次学习,应该对G1有了很好的认识。
- 吞吐量-响应能力兼顾
- G1收集器的设计目标和设计规划
- HotSpot虚拟机的主要构成
- 传统垃圾收集器堆结构
- G1收集器堆结构
- G1和CMS的对比、优势
- G1的重要概念:Region分区-CSet已收集集合-RSet已记忆集合-SATB增量式标记算法
- G1 GC模式:Young GC - Mixed GC、两种都是STW
- 全局并发标记:Global Concurrent Marking。主要是为Mixed GC提供标记服务
- G1在运行过程中的主要模式。YGC、并发阶段、混合模式、Full GC
- YGC:对所有的新生代都进行GC
- 并发阶段:全局并发标记阶段。
- 混合模式:MIXedGC,先执行YGC,对回收性价比比较高的进行回收
- Full GC,并不属于G1,在极端情况下,Mixed跟不上速度,只能*调用FullGC
- Humongous区域
- card table结构。(RSet)(Point-in Point-out 指向引用和被引用对象)
- Young GC
- Mixed GC
- 三色标记算法(追踪式跟踪使用的算法)
- G1分代算法
- SATB(SnapShot at the beginning)
- Evacuation Failure
以上都是概念性的描述。
通过实例查看G1日志
方向性的建议
- 概念肯定是要知道的。然后再实践。针对底层原理要精读,慢啃。
- 对于JVM的学习,不要东一棒槌,西一榔头的。全面的涉及。
- 记录记录记录,学习的时候记住了,之后肯定会忘记
学习没有任何捷径。研读源码。网上的文章一般都是到底层的时候,就结束了。
- openjdk.java.net
看别人,是偷懒的表现,能够让自己不用经过大脑思考,不经过自己的努力就能够获取到,而往往也不珍惜。
2020年02月23日11:16:24
关于JVM的学习暂时先到这里。