G1是一个:
G1把整个heap分为~2048个Region,尺寸在1M-32M之间(得是2的指数)。
Region分为:Eden,Survior,H(巨大对象),Old区。Eden和Survivor组合成Young Region。H是Old区的一种。一个对象尺寸超过Region的1/2,就是巨大对象,巨大对象直接分配在Old区,并被标记为H。
YGC,采用复制算法,并行的。
YGC逻辑上和其他GC算法一样的,也是Eden和S-From -> S-To和Old。
Heap使用超过一定比例会触发对Old Region并发标记(注意只标记,不回收),-XX:InitiatingHeapOccupancyPercent,默认45,
并发标记的阶段:
在标记过程中每个对象会被标记成三种颜色:
所有标记完成后,会把白色的作为垃圾回收掉(因为不可达)。
把Collection Set里的待回收的Old Region混合到YGC里慢慢消化掉。
如果Mixed GC来不及回收掉空间,那么就会触发Full GC。会停止整个JVM。
Old GC是分层次进行的:
尺寸超过1/2 Region的对象被称为,H对象,直接分配在Old区里,这个区被标记为H。它要么在并发标记的清理阶段回收,要么在Full GC的时候回收。
G1假设大对象不是短命对象,因此把他们放到H区里可以避免被YGC反复复制,提高性能。
单如果你的大对象的确是短命的,那如果把他们放到H区里反而会增加Old GC的压力,还有可能导致Full GC。因此你可以通过调整 -XX:G1HeapRegionSize=16M
来调整Region的大小,从而使得你的大对象不被G1认定为H对象。
每个Region都有,记录了外部引用的信息(其他Region到自己Region的引用信息)。Card Table是一个特定类型的Remeber Set。
在YGC时,需要扫描Old Region里到Young Region里的引用,RSet可以提高扫描效率,而不需要遍历所有Old Region。
同时,因为YGC采用的复制算法,而且是并行的,那么某一时刻某个对象同时出现在两块Region里(比如,Eden和S),为了YGC之后修复引用(正确的应该是引用到S里),那么就需要Remember Set??这段论述在Monica的文章里似乎没有。
Remeber Set 三种粒度(下面讲的不是很明白):
三种粒度的关系是:当某种粒度的空间满了,就切换到下一种,从而节省空间。但是节省空间的结果就是增加了扫描的时间,因为记录的信息也粗了。
Card Table是一种特殊的Remember Set形式,它是一个bitmap,每个bit对应了Region中的一片区域,而这篇区域里有对象引用了我这个Region里的对象。
记录了需要收集的Region列表,这个在并发标记之后。对于YGC来说只有Young Region,对于Mixed GC来说,有Y也有Old。