1. G1 GC 的堆内存划分
# G1 采用的多个 Region 的方式划分堆内存,而不是简单的条带状划分方式;但它也有“年代”的概念。
也就是说“年代”在 G1 中是逻辑概念。部分 Region 会标记为属于 Eden,部分属于 Survivor,部分属于老年代。
# 每个 Region 大小相同;
最小值为 1MB,最大值为 32MB;但字节数必须是2的幂。
也可以通过 JVM 启动参数进行设置。如:
-XX:G1HeapRegionSize=16M
# JVM 会尽量划分出 2048 个 Region
class HeapRegionBounds : public AllStatic {
private:
// Minimum region size; we won't go lower than that.
// We might want to decrease this in the future, to deal with small
// heaps a bit more efficiently.
static const size_t MIN_REGION_SIZE = 1024 * 1024;
// Maximum region size; we don't go higher than that. There's a good
// reason for having an upper bound. We don't want regions to get too
// large, otherwise cleanup's effectiveness would decrease as there
// will be fewer opportunities to find totally empty regions after
// marking.
static const size_t MAX_REGION_SIZE = 32 * 1024 * 1024;
// The automatic region size calculation will try to have around this
// many regions in the heap (based on the min heap size).
static const size_t TARGET_REGION_NUMBER = 2048;
public:
static inline size_t min_size();
static inline size_t max_size();
static inline size_t target_number();
};
# G1 中的大对象
超过 Region 50% 大小的对象被划分为大对象(Humongous)
大对象一般是大的 byte 或 char 数组
Humongous属于老年代。因为大对象的复制太耗时,所以直接被划为老年代可以减少 Minor GC 的消时。
与条带式划分不同,Region 式的划分可能因为大对象实在太大,而没有连续的 Region 可供放置。
此时可以通过指定一个更大的 Region 容量来规避该问题
2. G1 的基本算法概念
2.1 复合算法
G1 GC 是一种采用复合算法的 GC。
2.1.1 新生代
采用并行的复制算法(这会有 STW 停顿)
2.1.2 老年代
大部分情况下是并发标记(Mark);
整理(Compact)操作是在新生代 GC 时捎带执行的
而且整理操作是增量式的,而整体式整理
2.1.3 GC 状态流转顺序(循环)
1. Minor GC
2. Minor GC + Concurrent Mark
3. Mixed GC
2.1.4 对大对象(Humongous )的特殊“关照”
通常,应用中的大对象数量比较少。G1 利用这点,在 Minor GC 时就会清理大对象(即使它属于老年代)
Minor GC 本就会检查是否有新生代对象引用了大对象;
大对象数量少,所以检查是否有老年代对象引用大对象的的总体耗时(T)也少;
这样,只需额外消耗较短的时间 T,就能确定大对象是否可以被清理;
所以在 Minor GC 中清理大对象也是一种值得的策略。
2.1.5 字符串排重
JDK 8u20 之后,G1 会对字符串进行 排重 ——将指向相同字符串(不同实例)的引用指向同一个字符串引用
Minor GC中,在 Yong GC 后,JVM 会并发地执行该排重操作(不会 STW)
通过 JVM 参数开启该特性:-XX:+UseStringDeduplication
2.1.6 类卸载
JDK 8u40 之后,G1 默认在并发标记结束后就进行类卸载
-XX:+ClassUnloadingWithConcurrentMark
2.2 Minor GC
对新生代的 GC 一般称为 Minor GC
但 G1 的 Minor GC 会涉及 Remembered Set 的处理
2.3 Mixed GC
Mixed GC 包括对新生代和老年代的 GC
G1 的 Mixed GC 会清理部分老年代内存。可通过相关 JVM 参数设置其行为:
设定 Mixed GC 清理老年代内存的触发阀值
老年代Region数与总Region数的比值达到该值时,将在 Mixed GC 中清理老年代
-XX:G1MixedGCLiveThresholdPercent=85
设定 Mixed GC 中清理老年代内存的Region数(比例)
这是相对与总 Region 数的占比
-XX:G1OldCSetRegionThresholdPercent=10
2.4 Remembered Set
它记录了 Region 之间对象的引用关系,用于保证GC时对象被赋值到另一个Region后,其它对象对它的引用仍然有效。
对 Remember Set 的操作占用 G1 很多资源。
Remember Set 通常会占用堆的 20%
Card Table 的扫描和修改是比较耗时的,会直接影响 STW 的时间
Card Table 是Remember Set 的一种实现