CMS、G1、ZGC的堆内存实现区别

每次被问到Java的堆内存是如何细分?

很多人回答这个问题的时候,都是上来就直接说新生代和老年代,以为所有算法的内存实现都一样。

其实CMS、G1、ZGC的堆内存实现是不同的。我们可以从这三种垃圾回收器的堆内存实现更好地回答这个问题。

CMS

CMS堆内存和以往的垃圾回收器一样,分为新生代和老年代,新生代和老年代是物理隔离的。
CMS、G1、ZGC的堆内存实现区别
这些space必须是地址连续的空间。

G1

G1打破了以往将收集范围固定在新生代或老年代的模式,G1将堆分成许多相同大小的区域单元,每个单元称为Region。Region是一块地址连续的内存空间。

Region的大小是一致的,堆内存中一个Region的大小可以通过 -XX:G1HeapRegionSize参数指定,大小区间只能是1M、2M、4M、8M、16M和32M,总之是2的幂次方,JVM会默认划分2048个、同等大小的Region。

CMS、G1、ZGC的堆内存实现区别

每块区域既有可能属于O区、也有可能是Y区,且每类区域空间可以是不连续的(对比CMS的O区和Y区都必须是连续的)

ZGC

和G1类似,但ZGC的region的大小更加灵活和动态。zgc的region不会像G1那样在一开始就被划分为固定大小的region。

zgc的region核心亮点就是:动态。

动态表现为:

  1. 动态地创建和销毁。
  2. 动态地决定region的大小。它的最小单位是2MB的一个块。然后每个region的大小就是是2MB*N就是。

而且他有个概念叫:size groups。有三种:

  • Small:就是一个2MB的region。
  • Medium:32mb。2MB*16。
  • Large:N*2MB。

整个heap长这样:
CMS、G1、ZGC的堆内存实现区别