JVM垃圾收集器之G1

JVM垃圾收集器

一.G1垃圾收集器

1.G1采用内存分区(Region)的思路,将内存划分为一个个相等大小的内存分区,回收时则以分区为单位进行回收,存活的对象复制到另一个空闲分区中。由于都是以相等大小的分区为单位进行操作,因此G1天然就是一种压缩方案(局部压缩),G1收集器(或者垃圾优先收集器)的设计初衷是为了尽量缩短处理超大堆(大于4GB)时产生的停顿。相对于CMS的优势而言是内存碎片的产生率大大降低。

2.G1虽然也是分代收集器,但整个内存分区不存在物理上的年轻代与老年代的区别,也不需要完全独立的survivor(to space)堆做复制准备。G1只有逻辑上的分代概念,或者说每个分区都可能随G1的运行在不同代之间前后切换;

1.分区

分区 Region

G1采用了分区(Region)的思路,将整个堆空间分成若干个大小相等的内存区域,每次分配对象空间将逐段地使用内存。因此,在堆的使用上,G1并不要求对象的存储一定是物理上连续的,只要逻辑上连续即可;每个分区也不会确定地为某个代服务,可以按需在年轻代和老年代之间切换。启动时可以通过参数-XX:G1HeapRegionSize=n可指定分区大小(1MB~32MB,且必须是2的幂),默认将整堆划分为2048个分区。默认年轻代堆的占比是5%,当年轻代的对象占有了5%时,并不会立刻出发GC,而是与我们自己设定的停顿时间进行比较,在运行过程中,jvm会不停的给年轻代增加更多的region,但是新生代的占比不会超过60%。年轻代中Eden和Survivor0和Survivor1对应的占比默认8:1:1。

2.巨型对象

巨型对象 Humongous Region

一个大小达到甚至超过分区大小一半的对象称为巨型对象(Humongous Object)。当线程为巨型分配空间时,不能简单在TLAB进行分配,因为巨型对象的移动成本很高,而且有可能一个分区不能容纳巨型对象。因此,巨型对象会直接在老年代分配,所占用的连续空间称为巨型分区(Humongous Region)。G1内部做了一个优化,一旦发现没有引用指向巨型对象,则可直接在年轻代收集周期中被回收。

巨型对象会独占一个、或多个连续分区,其中第一个分区被标记为开始巨型(StartsHumongous),相邻连续分区被标记为连续巨型(ContinuesHumongous)。由于无法享受Lab带来的优化,并且确定一片连续的内存空间需要扫描整堆,因此确定巨型对象开始位置的成本非常高,如果可以,应用程序应避免生成巨型对象。

G1垃圾收集器之所以将大对象放置到Humongous区,是为了让老年代区域能更多地放置一些小对象。

1.初始标记
标记一下GC Roots能直接关联到的对象,要停止线程但耗时很短。
2.并发标记
从GC Roots开始对堆中的对象进行可达性分析,找到存活的对象但耗时较长,可与用户线程并发执行。
3.最终标记
为了修正在并发标记阶段,因用户线程继续运行,而导致的标记变动的那部分对象,但要停止线程。
4.筛选回收
我们可以自己指定回收时间,对各个region的回收价值和成本进行排序,采用复制算法,回收时则以分区为单位进行回收,存活的对象复制到另一个空闲分区中,故不会产生内存碎片。

3.G1垃圾收集器参数

-XX:+UseG1GC 采用 Garbage First (G1) 收集器
-XX:InitiatingHeapOccupancyPercent=n
设置触发标记周期老年代堆内存占 Java 堆阈值。默认占用率是整个 Java 堆的 45%。默认值 45.,触发MixedGC。

4.G1垃圾收集分类

YoungGC
YoungGC并不是说年轻代的Eden区放满了就触发,而是会预计Eden区回收要多长时间去和自己设定的停止参数比较,如果差得远那么就继续申请年轻代的region,继续给新对象存放,直到某一次Eden区再次放满G1计算回收时间与设定接近,那么就会触发YoungGC。
MixedGC
当老年代的堆占有率达到参数设定的值(默认45%)时才会触发,回收所有young区域和根据期望的GC停顿时间来确定old区垃圾回收的优先顺序以及大对象区,正常情况下G1的垃圾收集先是做MixedGC,主要使用复制算法,需要把region中存活的对象拷贝到别的region中,拷贝过程如果没有足够的region去使用,就会触发一次Full GC
Full GC
停止系统程序,然后使用单线程进行标记、清理,而后空闲出来的region来供下一次MixedGC来使用,过程十分耗时。

5.G1适合的场景

1.50%以上的堆被存活对象占有
2.对象分配和晋升的速度变化非常大
3.垃圾回收的时间特别长,超过1秒
4.8GB以上的堆内存
5.停顿时间500ms以内

创作时间:2019年11月21日20:08:15于天目酒店

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JVM (Java Virtual Machine) G1 (Garbage-First) 垃圾收集器是一种用于 Java 应用程序的垃圾收集算法。它是自JDK 7u4版本后引入的一种全新的垃圾收集器G1垃圾收集器的设计目标是为了解决传统的分代垃圾收集器可能遇到的一些问题,如停顿时间长、内存碎片化等。它采用了一种基于区域的垃圾收集方式,可以将内存划分为多个大小相等的区域,每个区域可以是Eden、Survivor或Old区。 G1垃圾收集器的工作原理如下: 1. 初始标记(Initial Mark):标记所有从根对象直接可达的对象。 2. 并发标记(Concurrent Mark):在并发执行程序的同时,标记那些在初始标记阶段无法访问到的对象。 3. 最终标记(Final Mark):为并发标记阶段中发生改变的对象进行最终标记。 4. 筛选回收(Live Data Counting and Evacuation):根据各个区域的回收价值来优先回收价值低的区域。 G1垃圾收集器具有以下特点: - 并发执行:在执行垃圾收集过程时,尽可能减少应用程序的停顿时间。 - 分区回收:将整个堆划分为多个区域,可以根据需要优先回收垃圾较多的区域,从而避免全堆回收带来的长时间停顿。 - 内存整理:G1垃圾收集器会对内存进行整理,减少内存碎片化,提高内存利用率。 需要注意的是,G1垃圾收集器并不适用于所有情况。在特定的场景下,如大堆情况下的长时间运行、对延迟要求非常高的应用等,可能需要考虑其他垃圾收集器的使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值