详细了解G1、了解G1、G1垃圾收集器详解、G1垃圾回收器简单调优

这篇具有很好参考价值的文章主要介绍了详细了解G1、了解G1、G1垃圾收集器详解、G1垃圾回收器简单调优。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

4.详细了解G1:
4.1.一:什么是垃圾回收
4.2.了解G1
4.3.G1 Yong GC
4.4.G1 Mix GC
4.5.三色标记算法
4.6.调优实践
5.G1垃圾收集器详解
5.1.G1垃圾收集器
5.2.G1的堆内存划分
5.3.G1的运行过程
5.4.三色标记
5.4.1.漏标问题
5.5.记忆集与卡表
5.6.安全点与安全区域
6.G1垃圾回收器简单调优
6.1.堆
6.2.Java 9以后开启的参数
6.3.G1的GC阶段
6.4.Young Only Phase
6.5.Mixed gc Phase
6.6.Full gc Phase
6.7.先来看看GC周期
6.8.gc日志

4.详细了解G1:

转自:https://www.cnblogs.com/lsgxeva/p/10231201.html

4.1.一:什么是垃圾回收

首先,在了解G1之前,我们需要清楚的知道,垃圾回收是什么?简单的说垃圾回收就是回收内存中不再使用的对象。

垃圾回收的基本步骤:
1.查找内存中不再使用的对象。
2.释放这些对象占用的内存。

1.查找内存中不再使用的对象
那么问题来了,如何判断哪些对象不再被使用呢?我们也有2个方法:
A:引用计数法
引用计数法就是如果一个对象没有被任何引用指向,则可视之为垃圾。这种方法的缺点就是不能检测到环的存在。

B:根搜索算法(可达性分析算法)
根搜索算法的基本思路就是通过一系列名为”GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。

现在我们已经知道如何找出垃圾对象了,如何把这些对象清理掉呢?

2.释放这些对象占用的内存
常见的方式有复制或者直接清理,但是直接清理会存在内存碎片,于是就会产生了清理再压缩的方式。

总得来说就产生了三种类型的回收算法。
A.标记–复制
它将可用内存容量划分为大小相等的两块,每次只使用其中的一块。当这一块用完之后,就将还存活的对象复制到另外一块上面,然后在把已使用过的内存空间一次理掉。它的优点是实现简单,效率高,不会存在内存碎片。缺点就是需要2倍的内存来管理。

B.标记–清理
标记清除算法分为”标记”和”清除”两个阶段:首先标记出需要回收的对象,标记完成之后统一清除对象。它的优点是效率高,缺点是容易产生内存碎片。

C.标记–整理
标记操作和”标记-清理”算法一致,后续操作不只是直接清理对象,而是在清理无用对象完成后让所有存活的对象都向一端移动,并更新引用其对象的指针。因为要移动对象,所以它的效率要比“标记-清理”效率低,但是不会产生内存碎片。

3.基于分代的假设
由于对象的存活时间有长有短,所以对于存活时间长的对象,减少被gc的次数可以避免不必要的开销。这样我们就把内存分成新生代和老年代,新生代存放刚创建的存活时间比较短的对象,

4.Java垃圾收集器的历史

  • 第一阶段,Serial(串行)收集器
    在jdk1.3.1之前,java虚拟机仅仅能使用Serial收集器。Serial收集器是一个单线程的收集器,但它的”单线程”的意义并不仅仅是说明它只会使用一个CPU或一条收集线程去完成垃圾收集工作,更重要的是在它进行垃圾收集时,必须暂停其他所有的工作线程,直到它收集结束。

PS:开启Serial收集器的方式

-XX:+UseSerialGC
  • 第二阶段,Parallel(并行)收集器
    Parallel收集器也称吞吐量收集器,相比Serial收集器,Parallel最主要的优势在于使用多线程去完成垃圾清理工作,这样可以充分利用多核的特性,大幅降低gc时间。
    PS:开启Parallel收集器的方式
-XX:+UseParallelGC -XX:+UseParallelOldGC
  • 第三阶段,CMS(并发)收集器
    CMS收集器在Minor GC时会暂停所有的应用线程,并以多线程的方式进行垃圾回收。在Full GC时不再暂停应用线程,而是使用若干个后台线程定期的对老年代空间进行扫描,及时回收其中不再使用的对象。
    PS:开启CMS收集器的方式
-XX:+UseParNewGC -XX:+UseConcMarkSweepGC
  • 第四阶段,G1(并发)收集器
    G1收集器(或者垃圾优先收集器)的设计初衷是为了尽量缩短处理超大堆(大于4GB)时产生的停顿。相对于CMS的优势而言是内存碎片的产生率大大降低。

PS:开启G1收集器的方式

-XX:+UseG1GC

4.2.了解G1

G1的第一篇paper(附录1)发表于2004年,在2012年才在jdk1.7u4中可用。oracle官方计划在jdk9中将G1变成默认的垃圾收集器,以替代CMS。为何oracle要极力推荐G1呢,G1有哪些优点?

首先,G1的设计原则就是简单可行的性能调优
开发人员仅仅需要声明以下参数即可:

-XX:+UseG1GC -Xmx32g -XX:MaxGCPauseMillis=200

其中-XX:+UseG1GC为开启G1垃圾收集器,-Xmx32g设计堆内存的最大内存为32G,-XX:MaxGCPauseMillis=200设置GC的最大暂停时间为200ms。如果我们需要调优,在内存大小一定的情况下,我们只需要修改最大暂停时间即可。

其次,G1将新生代,老年代的物理空间划分取消了。
这样我们再也不用单独的空间对每个代进行设置了,不用担心每个代内存是否足够。
详细了解G1、了解G1、G1垃圾收集器详解、G1垃圾回收器简单调优,# JVM,jvm,java,算法

取而代之的是,G1算法将堆划分为若干个区域(Region),它仍然属于分代收集器。不过,这些区域的一部分包含新生代,新生代的垃圾收集依然采用暂停所有应用线程的方式,将存活对象拷贝到老年代或者Survivor空间。老年代也分成很多区域,G1收集器通过将对象从一个区域复制到另外一个区域,完成了清理工作。这就意味着,在正常的处理过程中,G1完成了堆的压缩(至少是部分堆的压缩),这样也就不会有cms内存碎片问题的存在了。
详细了解G1、了解G1、G1垃圾收集器详解、G1垃圾回收器简单调优,# JVM,jvm,java,算法

在G1中,还有一种特殊的区域,叫Humongous区域。 如果一个对象占用的空间超过了分区容量50%以上,G1收集器就认为这是一个巨型对象。这些巨型对象,默认直接会被分配在年老代,但是如果它是一个短期存在的巨型对象,就会对垃圾收集器造成负面影响。为了解决这个问题,G1划分了一个Humongous区,它用来专门存放巨型对象。如果一个H区装不下一个巨型对象,那么G1会寻找连续的H分区来存储。为了能找到连续的H区,有时候不得不启动Full GC。

PS:在java 8中,持久代也移动到了普通的堆内存空间中,改为元空间。

对象分配策略
说起大对象的分配,我们不得不谈谈对象的分配策略。它分为3个阶段:
1.TLAB(Thread Local Allocation Buffer)线程本地分配缓冲区。
2.Eden区中分配。
3.Humongous区分配。

TLAB为线程本地分配缓冲区,它的目的为了使对象尽可能快的分配出来。如果对象在一个共享的空间中分配,我们需要采用一些同步机制来管理这些空间内的空闲空间指针。在Eden空间中,每一个线程都有一个固定的分区用于分配对象,即一个TLAB。分配对象时,线程之间不再需要进行任何的同步。

对TLAB空间中无法分配的对象,JVM会尝试在Eden空间中进行分配。如果Eden空间无法容纳该对象,就只能在老年代中进行分配空间。

最后,G1提供了两种GC模式,Young GC和Mixed GC,两种都是Stop The World(STW)的。下面我们将分别介绍一下这2种模式。

4.3.G1 Yong GC

Young GC主要是对Eden区进行GC,它在Eden空间耗尽时会被触发。在这种情况下,Eden空间的数据移动到Survivor空间中,如果Survivor空间不够,Eden空间的部分数据会直接晋升到年老代空间。Survivor区的数据移动到新的Survivor区中,也有部分数据晋升到老年代空间中。最终Eden空间的数据为空,GC停止工作,应用线程继续执行。
详细了解G1、了解G1、G1垃圾收集器详解、G1垃圾回收器简单调优,# JVM,jvm,java,算法
详细了解G1、了解G1、G1垃圾收集器详解、G1垃圾回收器简单调优,# JVM,jvm,java,算法

这时,我们需要考虑一个问题,如果仅仅GC 新生代对象,我们如何找到所有的根对象呢? 老年代的所有对象都是根么?那这样扫描下来会耗费大量的时间。于是,G1引进了RSet的概念。它的全称是Remembered Set,作用是跟踪指向某个heap区内的对象引用。
详细了解G1、了解G1、G1垃圾收集器详解、G1垃圾回收器简单调优,# JVM,jvm,java,算法

在CMS中,也有RSet的概念,在老年代中有一块区域用来记录指向新生代的引用。这是一种point-out,在进行Young GC时,扫描根时,仅仅需要扫描这一块区域,而不需要扫描整个老年代。

但在G1中,并没有使用point-out,这是由于一个分区太小,分区数量太多,如果是用point-out的话,会造成大量的扫描浪费,有些根本不需要GC的分区引用也扫描了。于是G1中使用point-in来解决。point-in的意思是哪些分区引用了当前分区中的对象。这样,仅仅将这些对象当做根来扫描就避免了无效的扫描。由于新生代有多个,那么我们需要在新生代之间记录引用吗?这是不必要的,原因在于每次GC时,所有新生代都会被扫描,所以只需要记录老年代到新生代之间的引用即可。

需要注意的是,如果引用的对象很多,赋值器需要对每个引用做处理,赋值器开销会很大,为了解决赋值器开销这个问题,在G1 中又引入了另外一个概念,卡表(Card Table)。一个Card Table将一个分区在逻辑上划分为固定大小的连续区域,每个区域称之为卡。卡通常较小,介于128到512字节之间。Card Table通常为字节数组,由Card的索引(即数组下标)来标识每个分区的空间地址。默认情况下,每个卡都未被引用。当一个地址空间被引用时,这个地址空间对应的数组索引的值被标记为”0″,即标记为脏被引用,此外RSet也将这个数组下标记录下来。一般情况下,这个RSet其实是一个Hash Table,Key是别的Region的起始地址,Value是一个集合,里面的元素是Card Table的Index。

Young GC阶段:

  • 阶段1:根扫描
    静态和本地对象被扫描。

  • 阶段2:更新RS
    处理dirty card队列更新RS。

  • 阶段3:处理RS
    检测从年轻代指向年老代的对象。

  • 阶段4:对象拷贝
    拷贝存活的对象到survivor/old区域。

  • 阶段5:处理引用队列
    软引用,弱引用,虚引用处理。

4.4.G1 Mix GC

Mix GC不仅进行正常的新生代垃圾收集,同时也回收部分后台扫描线程标记的老年代分区。

它的GC步骤分2步:

  • 全局并发标记(global concurrent marking)
  • 拷贝存活对象(evacuation)

在进行Mix GC之前,会先进行global concurrent marking(全局并发标记)。 global concurrent marking的执行过程是怎样的呢?

在G1 GC中,它主要是为Mixed GC提供标记服务的,并不是一次GC过程的一个必须环节。global concurrent marking的执行过程分为五个步骤:

  • 初始标记(initial mark,STW)
    在此阶段,G1 GC 对根进行标记。该阶段与常规的 (STW) 年轻代垃圾回收密切相关。

  • 根区域扫描(root region scan)
    G1 GC在初始标记的存活区扫描对老年代的引用,并标记被引用的对象。该阶段与应用程序(非STW)同时运行,并且只有完成该阶段后,才能开始下一次 STW 年轻代垃圾回收。

  • 并发标记(Concurrent Marking)
    G1 GC在整个堆中查找可访问的(存活的)对象。该阶段与应用程序同时运行,可以被STW 年轻代垃圾回收中断。

  • 最终标记(Remark,STW)
    该阶段是 STW 回收,帮助完成标记周期。G1 GC 清空 SATB 缓冲区,跟踪未被访问的存活对象,并执行引用处理。

  • 清除垃圾(Cleanup,STW)
    在这个最后阶段,G1 GC 执行统计和 RSet 净化的 STW 操作。在统计期间,G1 GC 会识别完全空闲的区域和可供进行混合垃圾回收的区域。清理阶段在将空白区域重置并返回到空闲列表时为部分并发。

4.5.三色标记算法

提到并发标记,我们不得不了解并发标记的三色标记算法。它是描述追踪式回收器的一种有用的方法,利用它可以推演回收器的正确性。 首先,我们将对象分成三种类型的。

  • 黑色:根对象,或者该对象与它的子对象都被扫描。
  • 灰色:对象本身被扫描,但还没扫描完该对象中的子对象。
  • 白色:未被扫描对象,扫描完成所有对象之后,最终为白色的为不可达对象,即垃圾对象

当GC开始扫描对象时,按照如下图步骤进行对象的扫描:
根对象被置为黑色,子对象被置为灰色。
详细了解G1、了解G1、G1垃圾收集器详解、G1垃圾回收器简单调优,# JVM,jvm,java,算法
继续由灰色遍历,将已扫描了子对象的对象置为黑色。
详细了解G1、了解G1、G1垃圾收集器详解、G1垃圾回收器简单调优,# JVM,jvm,java,算法
遍历了所有可达的对象后,所有可达的对象都变成了黑色。不可达的对象即为白色,需要被清理。
详细了解G1、了解G1、G1垃圾收集器详解、G1垃圾回收器简单调优,# JVM,jvm,java,算法

这看起来很美好,但是如果在标记过程中,应用程序也在运行,那么对象的指针就可能改变。这样的话,我们就会遇到一个问题:对象丢失问题。

我们看下面一种情况,当垃圾收集器扫描到下面情况时:
详细了解G1、了解G1、G1垃圾收集器详解、G1垃圾回收器简单调优,# JVM,jvm,java,算法
这时候应用程序执行了以下操作:

A.c = C
B.c = null

这样,对象的状态图变成如下情形:
详细了解G1、了解G1、G1垃圾收集器详解、G1垃圾回收器简单调优,# JVM,jvm,java,算法

这时候垃圾收集器再标记扫描的时候就会下图成这样:
详细了解G1、了解G1、G1垃圾收集器详解、G1垃圾回收器简单调优,# JVM,jvm,java,算法
很显然,此时C是白色,被认为是垃圾需要清理掉,显然这是不合理的。那么我们如何保证应用在运行的时候,GC标记的对象不丢失呢?有如下2种可行的方式:
1.在插入的时候记录对象。
2.在删除的时候记录对象。

刚好这对应CMS和G1的2种不同实现方式:

在CMS采用的是增量更新(Incremental update),只要在写屏障(write barrier)里发现要有一个白对象的引用被赋值到一个黑对象 的字段里,那就把这个白对象变成灰色的。即插入的时候记录下来。

在G1中,使用的是STAB(snapshot-at-the-beginning)的方式,删除的时候记录所有的对象,它有3个步骤:

1,在开始标记的时候生成一个快照图标记存活对象
2,在并发标记的时候所有被改变的对象入队(在write barrier里把所有旧的引用所指向的对象都变成非白的)

3,可能存在游离的垃圾,将在下次被收集

这样,G1到现在可以知道哪些老的分区可回收垃圾最多。 当全局并发标记完成后,在某个时刻,就开始了Mix GC。这些垃圾回收被称作“混合式”是因为他们不仅仅进行正常的新生代垃圾收集,同时也回收部分后台扫描线程标记的分区。混合式垃圾收集如下图:
详细了解G1、了解G1、G1垃圾收集器详解、G1垃圾回收器简单调优,# JVM,jvm,java,算法
混合式GC也是采用的复制的清理策略,当GC完成后,会重新释放空间。
详细了解G1、了解G1、G1垃圾收集器详解、G1垃圾回收器简单调优,# JVM,jvm,java,算法
至此,混合式GC告一段落了。下一小节我们讲进入调优实践。文章来源地址https://www.toymoban.com/news/detail-666054.html

</

到了这里,关于详细了解G1、了解G1、G1垃圾收集器详解、G1垃圾回收器简单调优的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 08-JVM垃圾收集器详解

    上一篇:07-垃圾收集算法详解 如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。 虽然我们对各个收集器进行比较,但并非为了挑选出一个最好的收集器。因为直到现在为止还没有最好的垃圾收集器出现,更加没有万能的垃圾收集器,我们能做

    2024年02月09日
    浏览(50)
  • 深入理解JAVA垃圾收集器CMS,G1工作流程原理 GC流程图 什么社会触发Minor GC?触发MinorGC过程。Full GC 过程。

    JVM内存空间基础知识点(基于JDk1.8) 1.方法区:逻辑概念,元空间,方法区主要用于存储类的信息、常量池、方法数据、方法代码等。方法区逻辑上属于堆的一部分,但是为了与堆进行区分,通常又叫“非堆”。 2.程序计数器:程序计数器可以看作当前线程所执行的字节码的

    2024年04月25日
    浏览(41)
  • 【JVM】JVM收集器CMS与G1区别

    CMS收集器和G1收集器的区别 CMS收集器是老年代的收集器,可以配合新生代的Serial和ParNew收集器一起使用 G1收集器收集范围是老年代和新生代。不需要结合其他收集器使用 CMS收集器以最小的停顿时间为目标的收集器。 G1收集器可预测垃圾回收的停顿时间(建立可预测的停顿时间

    2024年02月08日
    浏览(84)
  • 从原理聊JVM(二):从串行收集器到分区收集开创者G1

    作者:京东科技 康志兴 随着Java的进化过程,涌现出各种不同的垃圾回收器,从串行执行到并行执行,从高吞吐到低延迟,终极目标就是让开发人员专注于程序的代码书写而无需关注内存管理。 JDK早期出现的垃圾回收器通常单独作用于不同分代,到后期出现的G1开始,才可以

    2023年04月24日
    浏览(36)
  • JVM(Java Virtual Machine)G1收集器篇

    本文参考《深入理解Java虚拟机》,本文主要介绍G1收集器的收集思想和具体过程(填上一篇文章留下的坑) 本系列其他文章链接: JVM(Java Virtual Machine)内存模型篇 JVM(Java Virtual Machine)垃圾收集算法篇 JVM(Java Virtual Machine)垃圾收集器篇 G1是一款主要面向服务端应用的垃圾

    2024年02月07日
    浏览(43)
  • 垃圾收集器

    目录 1.垃圾判断 1.1 引用计数法: 1.2 可达性分析: 1.3 常见的GC Roots有: 2.垃圾回收方式:垃圾收集器 2.1 CMS收集器: 2.2 G1收集器: 1.1 引用计数法:         对象有一个引用计数器,引用一次计数器就加1,计数器为0就是没有引用,但存在循环引用问题 1.2 可达性分析:

    2024年02月11日
    浏览(42)
  • JVM 垃圾收集器

    重点:CMS,G1,ZGC 主要垃圾收集器如下,图中标出了它们的工作区域、垃圾收集算法,以及配合关系。 Serial 收集器 Serial 收集器是最基础、历史最悠久的收集器。 如同它的名字(串行),它是一个单线程工作的收集器,使用一个处理器或一条收集线程去完成垃圾收集工作。

    2024年02月10日
    浏览(50)
  • 【JVM】JVM垃圾收集器

    垃圾收集器是负责 执行垃圾回收的组件 ,它们用于 管理Java程序运行时的内存分配和释放 。垃圾收集器的主要任务是 自动回收不再使用的内存对象 ,并将 内存空间重新回收 以供程序继续使用。 Serial和Serial Old串行垃圾收集器,是指 使用单线程进行垃圾回收 ,堆内存较小,

    2024年02月13日
    浏览(43)
  • JVM:垃圾收集器(7种)

    如果两个收集器之间存在连线,就说明它们可以搭配使用。它们说在的区域则表示这个收集器属于新生代收集器还是老年代收集器。其中Serial(串行)、Parallel(并行)         Serial收集器是最基础、历史最悠久的收集器,是HotSpot虚拟机新生代收集器的唯一选择。这个收集器

    2024年01月20日
    浏览(50)
  • JVM的故事——垃圾收集器

    新生代收集器,最基础的收集器,单线程。进行垃圾收集时必须暂停其他所有工作线程,stop the world 新生代收集器,实质上是serial收集器的多线程版本。除了serial,只有它能和CMS收集器(老年代收集器)配合工作。随着处理器核心数越来越多,parnew比serial有着更好的性能。(但如

    2024年02月10日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包