1.堆内存模型
1.分带收集的垃圾回收器
1.1新生带
1.1.1Serial
1.1.2ParNew
1.1.3Parallel Scavenge
1.2老年代
1.2.1Serial Old
1.2.2CMS
1.2.3Parallel Old
G1
分区
分区 Region
G1采用了分区(Region)的思路,将整个堆空间分成若干个大小相等的内存区域,每次分配对象空间将逐段地使用内存。因此,在堆的使用上,G1并不要求对象的存储一定是物理上连续的,只要逻辑上连续即可;每个分区也不会确定地为某个代服务,可以按需在年轻代和老年代之间切换。启动时可以通过参数-XX:G1HeapRegionSize=n可指定分区大小(必须在1MB~32MB,之间,且是2的N次幂),默认将整堆划分为2048个分区。
卡片
卡片 Card
在每个分区内部又被分成了若干个大小为512 Byte卡片(Card),标识堆内存最小可用粒度所有分区的卡片将会记录在全局卡片表(Global Card Table)中,分配的对象会占用物理上连续的若干个卡片,当查找对分区内对象的引用时便可通过记录卡片来查找该引用对象(见RSet)。每次对内存的回收,都是对指定分区的卡片进行处理。
已记忆集合 Remember Set (RSet)
在串行和并行收集器中,GC通过整堆扫描,来确定对象是否处于可达路径中。然而G1为了避免STW式的整堆扫描,在每个分区记录了一个已记忆集合(RSet),内部类似一个反向指针,记录引用分区内对象的卡片索引。当要回收该分区时,通过扫描分区的RSet,来确定引用本分区内的对象是否存活,进而确定本分区内的对象存活情况。
事实上,并非所有的引用都需要记录在RSet中,如果一个分区确定需要扫描,那么无需RSet也可以无遗漏的得到引用关系。那么引用源自本分区的对象,当然不用落入RSet中;同时,G1 GC每次都会对年轻代进行整体收集,因此引用源自年轻代的对象,也不需要在RSet中记录。最后只有老年代的分区可能会有RSet记录,这些分区称为拥有RSet分区(an RSet’s owning region)。
内部细节
- 2种GC
1.Fully Young GC
2.Mixed GC - 无需回收整个堆,而是选择一个Collection Set(CS)
- 估计每个Region中的垃圾比例,优先回收垃圾多的Region
问题
跨代 / 跨Region引用
这个时候,eden区有对象被老年代引用,所以不能安全的回收
于是引入Card Table 和 Remembered Set (Rset)
Rset是什么?
每个Region被分成大小为512 Byte卡片(Card),分配的对象会占用物理上连续的若干个卡片,每个Region都包含一个RSet,这个RSet就记录了不同Region中之间的卡片引用,在扫描时只用扫描RSet这个结构
垃圾收集
G1仍然保留了新生代和老年代的概念
新生代收集过程如下图
新生代收集把原来的绿色区进行回收,回收不了的放在深绿色区域。
老年带收集过程
老年带收集的时候也把新生代收集了,也叫Mix GC
1.初始标记 => GC Root对象和这些GC Root对象所在的Region,又叫Root Region,会STW
2.把刚刚得到的Root Region,扫描old区的所有Region,看这个Region区的Rset中是否有引用,如果有则标识出来
3.并发标记 => 只需要遍历刚刚标记的区域
4.最总标记 => 使用SATB (STW)
5.清理 => 只选出垃圾较多的region,如下图
G1总结
●软实时、低延时、可设定目标
●JDK9+的默认GC (JEP248)
●适用于较大的堆(>4~6G)
●用于替代CMS
设计目标:
尽可能少的不需要调优
一般调优使用-XX:MaxGCPauseMillis=N 去设定最大STW停顿时间
在未来的收集器(实验性):
ZGC
Shenandoah
常见的问题
1、ParNew + CMS的组合让我们有哪些痛点?
痛点:STW,且停顿时间不可控
G1垃圾回收器比~更好的垃圾回收性能
2、G1垃圾回收器
G1 同时回收新生代和老年代的对象,把java堆拆分为多个大小相等的Region。
最大特点:可以设置 ‘预期停顿时间’,G1全权负责达到这个目标,控制回收对性能的影响
3、G1是如何做到对垃圾回收导致的系统停顿可控的?
1-通过把内存拆分为大量小Region。
2-追踪每个Region的回收价值 - 有多少垃圾、回收这些垃圾预估耗时多少。
3-在设置的垃圾回收时间内,选择回收价值最好的进行回收
??表述中‘设置预期停顿时间’,G1全权负责,保证达到这个目标,后面表述‘尽量控制在指定的时间范围’,请问会存在回收时间超时的现象么?
答:几乎不会
??、如果在指定的时间内,回收的空间满足不了新对象的空间需求会怎样?是继续触发回收还是oom
答:继续触发回收
4、Region可能属于新生代也可能属于老年代
新生代和老年代各自的内存区域是不停的变动的,由G1自动控制。
??状态转换:新生代和老年代各自的内存区域是不停的变动,新生代变为老年代可以理解,老年代会变为新生代么?我猜想应该不会,可能老年代的Region空间全部回收完了,可能从老年代 变成 初始状态(非新非老),然后变成新生代,这样循环轮回。
答:Region变空后才会改变分代属性