JVM性能优化(三)G1垃圾收集器(1)

简介: JVM性能优化(三)G1垃圾收集器

一、简介


G1垃圾收集器是在jdk1.7中正式使用的全新的垃圾收集器,oracle官方计划在jdk9中将G1变成默认的垃圾收集器,以替代CMS


G1的设计 原则就是简化JVM性能调优,开发人员只需要简单的三步即可完成调优:


第一步:开启G1垃圾收集器

第二步:设置堆的最大内存

第三步:设置最大的停顿时间

G1中提供了三种模式垃圾回收模式,Young GC、Mixed GC 和 Full GC ,在不同的条件下被触发。


二、原理


G1垃圾收集器相比于其他收集器而言,最大的区别在于它取消了年轻代、老年代的物理划分,取而代之的是将堆划分为若干个区域(Region),这些区域中包含了有逻辑上的年轻代、老年代区域

这样做的好处就是,我们再也不用单独的空间对每个代进行设置了,不用担心每个代内存是否足够。


屏幕快照 2022-05-10 下午3.29.41.png

在G1划分区域中,年轻代垃圾收集器依然采用暂停所有应用线程的方式,将存活对象拷贝到老年代或者Survivor空间,G1收集器通过将对象从一个区域复制到另一个区域,完成了清理工作。


这就意味着,在正常的处理过程中,G1完成了堆的压缩(至少是部分堆的压缩),这样也就不会有CMS内存碎片问题的存在了,


在G1中,有一种特殊的区域,叫Humongous区域。


如果一个对象占用的空间超过了分区容量50%以上,G1收集器就认为这是一个巨型对象

这些巨型对象,默认直接会被分配在老年代,但是如果它是一个短期存在的巨型对象,就会对垃圾收集器造成负面影响。

为了解决这个问题,G1划分了一个Humongous区,它用来专门存放巨型对象,如果一个H区装不下一个巨型对象,那么G1会寻找连续的H分区存储,为了能找到连续的H区,有时候不得不启动 Full GC

三、Young GC


Young GC主要是对Eden区进行GC,它在Eden空间耗尽时会被触发。


Eden 空间的数据移动到Survivor 空间中,如果Survivor空间不够,Eden空间的部分数据会直接晋升到年老代空间

Survivor区的数据移动到新的Survivor区中,也有部分数据晋升到老年代空间中

最终Eden空间的数据为空,GC停止工作,应用线程继续执行


屏幕快照 2022-05-10 下午3.29.54.png

3.1、Remembered Set(已记忆集合)


在GC年轻代的对象时,我们如何找到年轻代中对象的根对象呢?

根对象可能是在年轻代中,也可以在老年代中,那么老年代的所有对象都是根吗?

如果全量扫描老年代,那么这样扫描下来会耗费大量的时间

于是,G1引进了Rset的概念,它的全称是 Remembered Set,其作用是跟踪执行某个堆内的对象引用

image.png

每个Region初始化时,会初始化一个remembered set(已记忆集合),这个翻译有点拗口,以下简称RSet,该集合用来记录并跟踪其它Region指向该Region中对象的引用,每个Region默认按照512Kb划分成多个Card,所以RSet需要记录的东西应该是 xx Region的 xx Card。


3.2、Mixed GC


当越来越多的对象晋升到老年代Old Region时,为了避免堆内存被耗尽,虚拟机会触发一个混合的垃圾收集器,既Mixed GC,该算法并不是一个Old GC,除了回收整个Young Region,还会回收一部分的Old Region,这里需要注意:是一部分老年代,而不是全部老年代,可以选择那些Old region 进行收集,从而可以对垃圾回收的耗时时间进行控制,也要注意的是Mixed GC并不是Full GC

Mixed GC什么时候出发?由参数 -XX:InitiatingHeapOccupancyPercent=n决定。默认:45%,该参数的意思是:当老年代大小占用整个堆大小百分比达到该阈值时触发。


它的GC步骤分两步:

1. 全局并发标记(global concurrent marking)

2. 拷贝存活对象(evacuation)


3.2.1 全局并发标记


全局并发标记,执行过程分为五个步骤:


**初始标记(initial mark ,STW):**标记从根节点直接可达的对象,这个阶段会执行一次年轻代GC,会产生全局停顿。


根区域扫描(root region scan):


G1 GC在初始标记的存活区扫描对老年代的引用,并标记被引用的对象

该阶段与应用程序(非STW)同时运行,并且只有完成该阶段后,才能开始下一次STW年轻代垃圾回收。

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


重新标记(Remark,STW): 该阶段是STW回收,因为程序在运行,针对上一次的标记进行修改。


清楚垃圾(Cleanup,STW): 轻点和重置标记状态,该阶段会STW,这个阶段并不会实际上去做垃圾的收集,等待evacuation阶段来回收


3.2.2 拷贝存活对象


Evacuation 阶段是全暂停的,该阶段把一部分Region里的活对象拷贝到另一部分Region中,从而实现垃圾的回收清理。


四、G1 收集器相关参数


-XX:+UseG1GC: 使用G1垃圾收集器


-XX:MaxGCPauseMillis: 设置期望达到最大GC停顿时间指标(JVM会尽力实现,但不保证达到),默认值是200毫秒


-XX:G1HeapRegionSize=n:


设置的G1区域的大小,值是2的幂,范围是 1MB 到 32MB之间,目标是根据最小的Java堆大小划分出约2048个区域

默认 是堆内存的1/2000

-XX:ParallelGCThreads=n: 设置STW 工作线程数的值,将 n的值设置为逻辑处理器的数量,n的值与逻辑处理器的数量相同,最多为8


-XX:ConcGCThreads=n: 设置并行标记的线程数,将n设置为并行垃圾回收线程数(ParallelGCThreads)的1/4左右


**-XX:InitiatingHeapOccupancyPercent=n: **设置出发标记周期的java堆占用率阈值,默认占用率是这个Java堆的45%


目录
相关文章
|
4月前
|
存储 算法 Oracle
极致八股文之JVM垃圾回收器G1&ZGC详解
本文作者分享了一些垃圾回收器的执行过程,希望给大家参考。
|
3月前
|
存储 算法 Java
jvm性能优化(一)-基于JDK1.8
jvm性能优化(一)-基于JDK1.8
|
1月前
|
SQL 缓存 监控
大厂面试高频:4 大性能优化策略(数据库、SQL、JVM等)
本文详细解析了数据库、缓存、异步处理和Web性能优化四大策略,系统性能优化必知必备,大厂面试高频。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:4 大性能优化策略(数据库、SQL、JVM等)
|
27天前
|
存储 算法 Java
JVM进阶调优系列(10)敢向stop the world喊卡的G1垃圾回收器 | 有必要讲透
本文详细介绍了G1垃圾回收器的背景、核心原理及其回收过程。G1,即Garbage First,旨在通过将堆内存划分为多个Region来实现低延时的垃圾回收,每个Region可以根据其垃圾回收的价值被优先回收。文章还探讨了G1的Young GC、Mixed GC以及Full GC的具体流程,并列出了G1回收器的核心参数配置,帮助读者更好地理解和优化G1的使用。
|
2月前
|
存储 算法 Java
Java虚拟机(JVM)的内存管理与性能优化
本文深入探讨了Java虚拟机(JVM)的内存管理机制,包括堆、栈、方法区等关键区域的功能与作用。通过分析垃圾回收算法和调优策略,旨在帮助开发者理解如何有效提升Java应用的性能。文章采用通俗易懂的语言,结合具体实例,使读者能够轻松掌握复杂的内存管理概念,并应用于实际开发中。
|
2月前
|
存储 监控 算法
JVM调优深度剖析:内存模型、垃圾收集、工具与实战
【10月更文挑战第9天】在Java开发领域,Java虚拟机(JVM)的性能调优是构建高性能、高并发系统不可或缺的一部分。作为一名资深架构师,深入理解JVM的内存模型、垃圾收集机制、调优工具及其实现原理,对于提升系统的整体性能和稳定性至关重要。本文将深入探讨这些内容,并提供针对单机几十万并发系统的JVM调优策略和Java代码示例。
60 2
|
3月前
|
存储 Java 编译器
🔍深入Android底层,揭秘JVM与ART的奥秘,性能优化新视角!🔬
【9月更文挑战第12天】在Android开发领域,深入了解其底层机制对提升应用性能至关重要。本文详述了从早期Dalvik虚拟机到现今Android Runtime(ART)的演变过程,揭示了ART通过预编译技术实现更快启动速度和更高执行效率的奥秘。文中还介绍了ART的编译器与运行时环境,并提出了减少DEX文件数量、优化代码结构及合理管理内存等多种性能优化策略。通过掌握这些知识,开发者可以从全新的角度提升应用性能。
79 11
|
4月前
|
存储 算法 Java
JVM自动内存管理之垃圾收集算法
文章概述了JVM内存管理和垃圾收集的基本概念,提供一个关于JVM内存管理和垃圾收集的基础理解框架。
JVM自动内存管理之垃圾收集算法
|
4月前
|
存储 算法 Java
JVM组成结构详解:类加载、运行时数据区、执行引擎与垃圾收集器的协同工作
【8月更文挑战第25天】Java虚拟机(JVM)是Java平台的核心,它使Java程序能在任何支持JVM的平台上运行。JVM包含复杂的结构,如类加载子系统、运行时数据区、执行引擎、本地库接口和垃圾收集器。例如,当运行含有第三方库的程序时,类加载子系统会加载必要的.class文件;运行时数据区管理程序数据,如对象实例存储在堆中;执行引擎执行字节码;本地库接口允许Java调用本地应用程序;垃圾收集器则负责清理不再使用的对象,防止内存泄漏。这些组件协同工作,确保了Java程序的高效运行。
34 3
|
4月前
|
C# UED 开发者
WPF打印功能实现秘籍:从页面到纸张,带你玩转WPF打印技术大揭秘!
【8月更文挑战第31天】在WPF应用开发中,打印功能至关重要,不仅能提升用户体验,还增强了应用的实用性。本文介绍WPF打印的基础概念与实现方法,涵盖页面元素打印、打印机设置及打印预览。通过具体案例,展示了如何利用`PrintDialog`和`PrintDocument`控件添加打印支持,并使用`PrinterSettings`类进行配置,最后通过`PrintPreviewWindow`实现打印预览功能。
463 0