JVM进阶(十一):JAVA G1收集器

JVM进阶(十一):JAVA G1收集器JVM进阶(十一)——JAVAG1收集器  在前两篇博文中讲解了新生代和年老代的收集器,在本篇博文中介绍一个收集范围涵盖整个堆的收集器——G1收集器。先讲讲G1收集器的特点,他也是个多线程的收集器,能够充分利用多个CPU进行工作,收集方式也与CMS收集器类似,因此不会有太久的停顿。  虽然回收的范围是整个堆,但还是有分代回收的回收方式。在年轻代依然采用复制算法;年老代也同样采用“标记-清除

大家好,又见面了,我是你们的朋友全栈君。

文章目录


一、前言

G1(Garbage First)垃圾收集器是当今垃圾回收技术最前沿的成果之一。早在JDK7就已加入JVM的收集器大家庭中,成为HotSpot重点发展的垃圾回收技术。同优秀的CMS垃圾回收器一样,G1也是关注最小时延的垃圾回收器,也同样适合大尺寸堆内存的垃圾收集,官方也推荐使用G1来代替选择CMSG1最大的特点是引入分区的思路,弱化了分代的概念,合理利用垃圾收集各个周期的资源,解决了其他收集器甚至CMS的众多缺陷。

在前两篇博文《JVM进阶(九):年轻代收集器》、《JVM进阶(十):年老代收集器》中讲解了新生代和年老代的收集器,在本篇博文中介绍一个收集范围涵盖整个堆的收集器:G1收集器

先讲讲G1收集器的特点,G1收集器也是个多线程的收集器,能够充分利用多个CPU进行工作,收集方式也与CMS收集器类似,因此不会有太久的停顿。

虽然回收的范围是整个堆,但还是有分代回收的回收方式。在年轻代依然采用复制算法年老代也同样采用“标记-清除-整理”算法。但是,新生代与老年代在堆内存中的布局就和以往的收集器有着很大的区别:G1将整个堆分成了一个个大小相等的独立区域,叫做region。其中依然保存着新生代和年老代的概念,如下图:
这里写图片描述
是不是和之前博文中看到的不同(这是内存空间图,不要和垃圾回收图弄混了),以往只是简单的分区域,而这里是将整个堆分成多个大小相等的区域。

他的回收过程也分为四个部分:初始标记、并发标记、最终标记、筛选回收

大家是不是觉得很熟悉!上面我们也说过了,和CMS收集器类似,初始标记需要STW;并发标记不需要;最终标记就是做一些小修改,需要STW;而筛选回收则有些不同,在众多的region中,每个region可回收的空间各不相同,但是回收所消耗的时间是需要控制的,不能太长,因此G1就会筛选出一些可回收空间比较大的region进行回收,这就是G1的优先回收机制。这也是保证了G1收集器能在有限的时间内能够获得最高回收效率的原因。通过-XX:MaxGCPauseMills=50毫秒设置有限的收集时间。

每个region之间的对象引用通过remembered set来维护,每个region都有一个remembered setremembered set中包含了引用当前region中对象的指针。虚拟机正是通过这个remembered set去避免对整个堆进行扫描来确认可回收的对象。

事实上,G1收集器与串行收集器、并行收集器、并发标记清除收集器这三组收集器有很大不同:

  • G1的设计原则是”首先收集尽可能多的垃圾(Garbage First)”。因此,G1并不会等内存耗尽(串行、并行)或者快耗尽(CMS)的时候开始垃圾收集,而是在内部采用了启发式算法,在老年代找出具有高收集收益的分区进行收集。同时G1可以根据用户设置的暂停时间目标自动调整年轻代和总堆大小,暂停目标越短年轻代空间越小、总空间就越大;
  • G1采用内存分区(Region)的思路,将内存划分为一个个相等大小的内存分区,回收时则以分区为单位进行回收,存活的对象复制到另一个空闲分区中。由于都是以相等大小的分区为单位进行操作,因此G1天然就是一种压缩方案(局部压缩);
  • G1虽然也是分代收集器,但整个内存分区不存在物理上的年轻代与老年代的区别,也不需要完全独立的survivor(to space)堆做复制准备。G1只有逻辑上的分代概念,或者说每个分区都可能随G1的运行在不同代之间前后切换;
  • G1的收集都是STW的,但年轻代和老年代的收集界限比较模糊,采用了混合(mixed)收集的方式。即每次收集既可能只收集年轻代分区(年轻代收集),也可能在收集年轻代的同时,包含部分老年代分区(混合收集),这样即使堆内存很大时,也可以限制收集范围,从而降低停顿。

到此,所有的收集器都已经讲完了,但是很重要的一点:每个收集器是不能随意进行组合使用的!这里我列出一个搭配使用的表格提供大家参考使用:
这里写图片描述
这里写图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/130728.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • pmf文件「建议收藏」

    pmf文件「建议收藏」1、首先是视频软件,其次还是DISKGENI(磁盘分区软件),当作镜像文件恢复文件到磁盘(类似ISO)。2、PMF文件为主要与primarilyPegasusMailMessageAttachment(DavidHarris)相关联的GIS文件。PMF文件还与以下相关联:PayrollMate2008(RealTaxTools.com),PCLToolPageTechM…

    2022年6月18日
    74
  • Java tps_Java static

    Java tps_Java static写在前面TPS即每秒查询事物,可以用于测试一个方法、工具或者系统的性能。本文采用Java并发包中的工具实现了一个工具TPS性能测试。主要是测试OKHttp库来执行Http请求的性能。测试代码用到了Java了线程池ExecuterService,CountDownLatch,CyclicBarrier,原子类,volatile关键词等。可算是对Java并发组件的组合使用。下面直接贴出源码,仅供参考

    2025年11月10日
    6
  • 解决Discuz! info: MySQL Query Error[通俗易懂]

    解决Discuz! info: MySQL Query Error[通俗易懂]php下安装Discuz!完成后点进bbs报错:Discuz!info:MySQLQueryErrorTime:2014-11-68:23amScript:/discuz7/bbs/in

    2022年7月3日
    32
  • 反演定理及其应用_反演定理的证明

    反演定理及其应用_反演定理的证明一、莫比乌斯反演莫比乌斯反演公式:若F(n)=∑i|nf(i)F(n)=∑i|nf(i)F(n)=\sum_{i|n}f(i)则f(n)=∑i|nμ(i)F(ni)f(n)=∑i|nμ(i)F(ni)f(n)=\sum_{i|n}\mu(i)F(\frac{n}{i})为什么呢?请看证明:由于莫比乌斯函数具有性质∑i|nμ(i)=[n=1]∑i|nμ(i)=[n=1]\…

    2025年8月21日
    4
  • JS生成随机数的算法

    JS生成随机数的算法关于随机数的过程解释:1>.Math.random()表示生成[0,1)的数,所以Math.random()*5生成的都是[0,4]的随机整数。2>Math.floor(num);参数num为一个数值,函数结果为num的整数部分。3>.Math.round(num);参数num为一个数值,函数结果为num四舍五入后的整数。4>.Math.cei…

    2022年7月14日
    22
  • 多进程和多线程区别以及优缺点[通俗易懂]

    多进程和多线程区别以及优缺点[通俗易懂]多进程和多线程主要区别是:线程是进程的子集,一个进程可能由多个线程组成。多进程的数据是分开的、共享复杂,需要用IPC,但同步简单;多线程共享进程数据、共享简单,但同步复杂。多进程,window应用程序中消息有两种送出途径:直接和排队。Windows或某些运行的应用程序可直接发布消息给窗口过程,消息可送到消息列象连续不断轮询消息列队的OS中当前执行的每个进程,事件驱动不是由事件的顺序来控制的,而是由事件的发生来控,而事件的发生是随机的、不确定的,这就允许程序的用户用各种合理的顺序来安排程序的流程。多线

    2025年7月9日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号