详解 JVM Garbage First(G1) 垃圾收集器

前言
Garbage First(G1)是垃圾收集领域的最新成果,同时也是HotSpot在JVM上力推的垃圾收集器,并赋予取代CMS的使命。如果使用Java 8/9,那么有很大可能希望对G1收集器进行评估。本文详细首先对JVM其他的垃圾收集器进行总结,并与G1进行了简单的对比;然后通过G1的内存模型、G1的活动周期,对G1的工作机制进行了介绍;同时还在介绍过程中,描述了可能需要引起注意的优化点。笔者希望通过本文,让有一定JVM基础的读者能尽快掌握G1的知识点。

第一章 概述

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

第二章 JVM GC收集器的回顾与比较

JVM GC收集器成员

从JDK3(1.3)开始,HotSpot团队一直努力朝着高效收集、减少停顿(STW: Stop The World)的方向努力,也贡献了从串行到CMS乃至最新的G1在内的一系列优秀的垃圾收集器。上图展示了JDK的垃圾回收大家庭,以及相互之间的组合关系,下面就几种典型的组合应用进行简单的介绍。

串行收集器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VllqSnjk-1600416354690)(https://c1.staticflickr.com/5/4603/28345836579_8dff90eb76_z.jpg)]

串行收集器组合 Serial + Serial Old

开启选项:-XX:+SerialGC

串行收集器是最基本、发展时间最长、久经考验的垃圾收集器,也是client模式下的默认收集器配置。

串行收集器采用单线程stop-the-world的方式进行收集。当内存不足时,串行GC设置停顿标识,待所有线程都进入安全点(Safepoint)时,应用线程暂停,串行GC开始工作,采用单线程方式回收空间并整理内存。单线程也意味着复杂度更低、占用内存更少,但同时也意味着不能有效利用多核优势。事实上,串行收集器特别适合堆内存不高、单核甚至双核CPU的场合。

并行收集器

并行收集器组合

并行收集器组合 Parallel Scavenge + Parallel Old

开启选项:-XX:+UseParallelGC-XX:+UseParallelOldGC(可互相激活)

并行收集器是以关注吞吐量为目标的垃圾收集器,也是server模式下的默认收集器配置,对吞吐量的关注主要体现在年轻代Parallel Scavenge收集器上。

并行收集器与串行收集器工作模式相似,都是stop-the-world方式,只是暂停时并行地进行垃圾收集。年轻代采用复制算法,老年代采用标记-整理,在回收的同时还会对内存进行压缩。关注吞吐量主要指年轻代的Parallel Scavenge收集器,通过两个目标参数-XX:MaxGCPauseMills-XX:GCTimeRatio,调整新生代空间大小,来降低GC触发的频率。并行收集器适合对吞吐量要求远远高于延迟要求的场景,并且在满足最差延时的情况下,并行收集器将提供最佳的吞吐量。

并发标记清除收集器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LeSnO6cw-1600416354703)(https://c1.staticflickr.com/5/4740/40093687062_7383cd1b49_z.jpg)]

并发标记清除收集器组合 ParNew + CMS + Serial Old

开启选项:-XX:+UseConcMarkSweepGC

并发标记清除(CMS)是以关注延迟为目标、十分优秀的垃圾回收算法,开启后,年轻代使用STW式的并行收集,老年代回收采用CMS进行垃圾回收,对延迟的关注也主要体现在老年代CMS上。

年轻代ParNew与并行收集器类似,而老年代CMS每个收集周期都要经历:初始标记、并发标记、重新标记、并发清除。其中,初始标记以STW的方式标记所有的根对象;并发标记则同应用线程一起并行,标记出根对象的可达路径;在进行垃圾回收前,CMS再以一个STW进行重新标记,标记那些由mutator线程(指引起数据变化的线程,即应用线程)修改而可能错过的可达对象;最后得到的不可达对象将在并发清除阶段进行回收。值得注意的是,初始标记和重新标记都已优化为多线程执行。CMS非常适合堆内存大、CPU核数多的服务器端应用,也是G1出现之前大型应用的首选收集器。

但是CMS并不完美,它有以下缺点:

  1. 由于并发进行,CMS在收集与应用线程会同时会增加对堆内存的占用,也就是说,CMS必须要在老年代堆内存用尽之前完成垃圾回收,否则CMS回收失败时,将触发担保机制,串行老年代收集器将会以STW的方式进行一次GC,从而造成较大停顿时间;
  2. 标记清除算法无法整理空间碎片,老年代空间会随着应用时长被逐步耗尽,最后将不得不通过担保机制对堆内存进行压缩。CMS也提供了参数-XX:CMSFullGCsBeForeCompaction(默认0,即每次都进行内存整理)来指定多少次CMS收集之后,进行一次压缩的Full GC。

Garbage First

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s3YrrBdC-1600416354705)(https://c1.staticflickr.com/5/4655/28345836209_7b70465317_b.jpg)]

Garbage First (G1)

开启选项:-XX:+UseG1GC

之前介绍的几组垃圾收集器组合,都有几个共同点:

  1. 年轻代、老年代是独立且连续的内存块;
  2. 年轻代收集使用单eden、双survivor进行复制算法;
  3. 老年代收集必须扫描整个老年代区域;
  4. 都是以尽可能少而块地执行GC为设计原则。

G1垃圾收集器也是以关注延迟为目标、服务器端应用的垃圾收集器,被HotSpot团队寄予取代CMS的使命,也是一个非常具有调优潜力的垃圾收集器。虽然G1也有类似CMS的收集动作:初始标记、并发标记、重新标记、清除、转移回收,并且也以一个串行收集器做担保机制,但单纯地以类似前三种的过程描述显得并不是很妥当。事实上,G1收集与以上三组收集器有很大不同:

  1. G1的设计原则是"首先收集尽可能多的垃圾(Garbage First)"。因此,G1并不会等内存耗尽(串行、并行)或者快耗尽(CMS)的时候开始垃圾收集,而是在内部采用了启发式算法,在老年代找出具有高收集收益的分区进行收集。同时G1可以根据用户设置的暂停时间目标自动调整年轻代和总堆大小,暂停目标越短年轻代空间越小、总空间就越大;
  2. G1采用内存分区(Region)的思路,将内存划分为一个个相等大小的内存分区,回收时则以分区为单位进行回收,存活的对象复制到另一个空闲分区中。由于都是以相等大小的分区为单位进行操作,因此G1天然就是一种压缩方案(局部压缩);
  3. G1虽然也是分代收集器,但整个内存分区不存在物理上的年轻代与老年代的区别,也不需要完全独立的survivor(to space)堆做复制准
  • 113
    点赞
  • 548
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 54
    评论
### 回答1: JVM是一种虚拟机(Java Virtual Machine),能够在不同操作系统和硬件平台上运行Java程序。而G1垃圾收集器JVM中的一种垃圾收集算法,可以处理大型Java堆。 使用G1垃圾收集器能够提高应用程序性能,因为它采用分区技术和优先级调度算法,可以根据应用程序的使用情况,动态地分配堆空间分区,从而减少垃圾收集时间和暂停时间。 下面是使用G1垃圾收集器来优化JVM的步骤: 第一步,设置JVM参数,例如开启G1垃圾收集器,设置堆空间大小等。 第二步,使用JVisualVM或其他工具,对应用程序进行分析,确定是否存在内存泄漏或内存过度消耗的现象。如果有问题,则需要对应用程序进行修改,以降低内存使用率。 第三步,对应用程序进行压测,确定最大并发并适当调整G1垃圾收集器参数,例如设置初始停顿时间、最大停顿时间、空闲时间等。 但需要注意的是,使用G1垃圾收集器时需要事先评估应用程序的运行环境和特性,例如硬件配置、每秒请求计数、响应时间等。只有在合适的环境下,G1垃圾收集器才能发挥最佳效果。同时,应用程序也需要符合一些条件,例如堆空间不能太小,内存消耗不能太大等。 总之,通过优化JVM,使用G1垃圾收集器能够提高Java应用程序的性能和可靠性,减少停顿时间。但使用时需要仔细评估和测试,确保最佳效果。 ### 回答2: JVM是Java虚拟机的缩写,是Java运行环境的核心部分。垃圾收集器JVM的一个重要组成部分,负责回收程序的无用对象和内存。G1垃圾收集器JVM中的一种,是目前比较流行的一种。下面介绍G1垃圾收集器的优化使用方法。 首先,G1垃圾收集器最大的优点是能够充分利用多核处理器和大内存的优势。因此,在使用G1垃圾收集器时,需要配置合适的垃圾回收线程数和堆内存大小。通常情况下,推荐将垃圾回收线程数设置为CPU核心数的一半左右,而堆内存大小则应根据应用程序的实际情况设定。 其次,G1垃圾收集器还支持增量垃圾回收和并发标记。这意味着垃圾收集器可以在应用程序执行的同时,进行部分的垃圾回收和标记操作。这有利于减少垃圾回收对应用程序执行的影响。 再次,G1垃圾收集器还支持混合模式。这种模式下,垃圾收集器会将堆内存分为多个区域,并按照各个区域的使用情况决定垃圾回收的策略。一些非常重要的区域可以在短时间内进行Full GC,而其它区域则可以使用增量式垃圾回收策略。这一功能可以进一步提高垃圾回收的效率。 最后,在使用G1垃圾收集器时,还需要注意一些细节问题。例如,需要选择合适的回收阈值、合理配置回收周期等等。此外,一些调试工具如JConsole、JVisualVM等也可以帮助开发者监控和调整G1垃圾收集器的性能。 总之,G1垃圾收集器是目前JVM中性能较优异的垃圾收集器之一。在使用G1垃圾收集器时,需要根据实际情况合理配置线程数、堆内存大小和一些参数,同时关注混合模式、增量垃圾回收和并发标记等特点,才能充分发挥其性能优势。 ### 回答3: JVM是Java虚拟机的缩写,它是Java程序运行的环境,它提供了一个平台无关的执行环境,能够提高Java应用程序的效率和安全性。Java应用程序的性能优化是一个复杂的过程,其中之一的重要方面是垃圾收集器的优化。 G1JVM中的一种垃圾收集器,它主要用于大堆内存应用程序,它在处理垃圾回收时可以实现高吞吐量和低延迟,而且它可以管理大容量的内存,能够处理高并发情况下的大量垃圾回收。 G1垃圾收集器具有以下优点: 1.低延迟:G1垃圾收集器能够有效地降低应用程序的延迟,因为它是一个分区式的垃圾收集器,它会将内存分成多个区域,每个区域都有自己的垃圾回收时间,这样可以最大程度的减少垃圾回收的时间。 2.高吞吐量:G1垃圾收集器能够管理大容量的内存,能够处理大量的垃圾回收,因此它的吞吐量很高。 3.可预测性:G1垃圾收集器能够实现可预测性垃圾回收,这意味着它可以为每个应用程序分配一个确定的垃圾回收时间,从而避免出现系统性能波动的情况。 4.自适应:G1垃圾收集器能够根据内存的使用情况来自动调整垃圾回收的策略,从而最大程度地优化垃圾回收的效率和性能。 在使用G1垃圾收集器时,需要注意以下几点: 1.适当配置参数:需要根据应用程序的实际情况,适当配置G1的参数,以提高垃圾回收的效率和性能。 2.避免频繁Full GCG1垃圾收集器能够尽量避免Full GC,但是在一些场景下,还是会出现Full GC的情况,因此需要尽量避免频繁Full GC的情况出现。 3.避免内存泄漏:G1垃圾收集器虽然能够处理大量垃圾,但是它无法处理内存泄漏的情况,因此需要及时发现和解决内存泄漏的问题。 总之,G1垃圾收集器是一个高性能、高效率的垃圾回收器,能够满足大堆内存应用程序的垃圾回收需求。在使用过程中,需要根据实际情况适当配置参数,避免频繁Full GC和内存泄漏的发生。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 54
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

coderlius

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值