java面试-G1垃圾收集器
一、以前收集器的特点
- 年轻代和老年代是各自独立且连续的内存块
- 年轻代收集器使用 eden + S0 + S1 进行复制算法
- 老年代收集必须扫描整个老年代区域
- 都是以尽可能的少而快速地执行 GC 为设计原则
二、G1 是什么
- G1 是一种面向服务端的垃圾收集器,应用在多核处理器和大容量内存环境中,在实现高吞吐量的同时,尽可能的满足垃圾收集器的暂停时间要求。
- 像 CMS 收集器一样,能与应用程序线程并发执行,
整理空闲空间更快,
需要更多的时间来预测 GC 停顿时间,
不希望牺牲大量的吞吐性能,不需要更大的 JAVA Heap。
- G1 收集器的设计目的是取代 CMS 收集器,同 CMS 相比,
G1 垃圾收集器是一个有整理内存过程的垃圾收集器,不会产生很多内存碎片。
G1 的 Stop The World 更可控,G1 在停顿上添加了预测机制,用户可以指定期望的停顿时间。
- G1 是在 2012 年才在 jdk.1.7u4 中可以呀用,在 jdk9 中将 G1 变成默认垃圾收集器来代替 CMS。它是一款面向服务应用的收集器。
主要改变是 Eden、Survivor 和 Tenured 等内存区域不再是连续的,而是变成了一个个大小一样的 region,每个 region 从 1M 到 32M 不等,一个 region 有可能属于 Eden、Survivor 或者 Tenured 内存区域。
三、特点
- G1 能充分利用多 CPU、多核环境硬件优势,尽量缩短 STW。
- G1 整体采用标记-整理算法,局部是通过是通过复制算法,不会产生内存碎片。
- 宏观上看 G1 之中不再区分年轻代和老年代,被内存划分为多个独立的子区域。
- G1 收集器里面讲整个的内存区域混合在一起,但其本身依然在小范围内要进行年轻代和老年代的区分。保留了新生代和老年代,但她们不在是物理隔离,而是一部分 Region 的集合且不需要 Region 是连续的,也就是说依然会采用不同的 GC 方式来处理不同的区域。
- G1 虽然也是分代收集器,但整个内存分区不存在物理上的年轻代和老年代的区别,也不需要完全独立的 Survivor to space 堆做复制准备。G1 只有逻辑上的分代概念,或者说每个分区都可能随 G1 的运行在不同代之间前后切换。
四、底层原理
1、Region 区域化垃圾收集器:最大好处是化整为零,避免全内存扫描,只需要按照区域来进行扫描即可。
2、回收步骤:
3、四步过程:
- 初始标记:标记一下GC Roots能直接关联到的对象,需要停顿线程,但耗时很短
- 并发标记:是从GC Root开始对堆中对象进行可达性分析,找出存活的对象,这阶段耗时较长,但可与用户程序并发执行
- 最终标记:修正在并发标记期间因用户程序继续运作而导致标记产生变动的那一部分标记记录
- 筛选回收:对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间来制定回收计划
五、常用配置参数:
-XX:UseG1GC
-XX:G1HeapRegionSize=n:设置G1区域的大小,值是2的幂
-XX:MaxGCPauseMillis=n:设置并行收集最大暂停时间
六、与CMS相比的优势
- 没有内存碎片
- 可以精确控制停顿