首页 > 其他分享 >JVM实战-G1参数调优

JVM实战-G1参数调优

时间:2023-12-21 18:45:03浏览次数:40  
标签:G1 Region 回收 XX 调优 GC 默认 JVM

G1简介

G1 GC,全称Garbage-First Garbage Collector,在JDK1.7中引入了G1 GC,从JAVA 9开始,G1 GC是默认的GC算法。通过-XX:+UseG1GC参数来启用。
G1收集器有分区概念,是工作在堆内不同分区上的收集器。G1的分区既可以是年轻代也可以是老年代,同一个代的分区不需要连续。
G1收集器在运行过程中,会自己调整新生代和老年代的Region数量,主要是通过adapt代的大小来调整对象晋升的速度和年龄,从而达到为收集器设置的暂停时间目标,因此不建议手动设置新生代和老年代的大小,只要设置整个堆的大小即可。
G1对Region的回收是基于复制算法进行的:将一个Region内的存活对象放入另一个Region中,再把这个Region的垃圾对象给清理掉,这样就不会产生内存碎片。

G1可以解决的场景包括:

堆大小可达数十 GB 或更大,超过 50% 的 Java 堆被实时数据占用。
对象分配和提升的速率可能会随时间而显著变化。
堆中存在大量碎片。
可预测的暂停时间目标目标不超过几百毫秒,避免长时间的垃圾回收暂停。

G1是设计用来取代CMS的,与CMS相比,G1有以下优势:

超大堆的表现更出色(CMS的STW时间会过长)
配置更少(G1具备一定的弹性调整能力)
在预测停顿时间上更稳定(CMS是全局扫描标记,G1是针对分区)
避免了CMS的垃圾碎片(G1是针对分区,使用复制算法)

G1相关参数配置

#使用G1垃圾收集器,在低延迟和高吞吐间寻找平衡,可以调整最大停止时间,设置新生代大小来提高吞吐量
-XX:+UseG1GC

#堆内存,示例设置最大最小值为4g,对于G1,一般建议2g以上。注意设定Xms=Xmx,防止发生扩容、缩容
-Xms4g -Xmx4g 

#配置元空间初始256m、最大256m。不配置的话,元空间会不受限地占用物理机内存
-XX:MetaspaceSize=256m  -XX:MaxMetaspaceSize=256m 
 
#设置最大暂停时间,默认200ms。G1收集回收器将堆进行分区,划分为一个个的区域,每次收集的时候,只收集其中几个区域,以此来控制垃圾回收产生一次停顿时间。
#暂停时间只是一个目标,并不能总是得到满足,G1会逐步调整到最佳状态。但若暂停时间设置的太短,就会导致出现G1跟不上垃圾产生的速度,最终退化成Full GC。
#在极端环境(如要求业务接口需要快速返回结果)下可尝试设置20ms以下,此时建议:精简下应用服务(减少实例的产生)、升级高版本jdk(17)、做好压测、长期关注。
-XX:MaxGCPauseMillis=100

#指定Region大小,必须是2次幂,最大是32m,具体取值有1MB、2MB、4MB、8MB、16MB、32MB。注意当对象占用内存超过Region的一半时将被视为大对象,被分配到Humongous区域
#可以预估应用服务的对象大小,确定Region大小。如果没有大对象的场景,则可尝试配置2m、1m,使单个Region能被快速回收
#该配置非必填,不声明时,Region大小等于堆大小除以2048
-XX:G1HeapRegionSize=2m

#针对混合回收回收的参数:混合回收不仅针对老年代,还有新生代和大对象
#老年代Region触发混合GC的占比,默认值是45,也就是说老年代占据了堆内存45%的Region的时,会触发混合GC。该值一般不需要调整,这样可以让JVM内存占用维持在50%左右
-XX:InitiatingHeapOccupancyPercent=45
#混合回收阶段会执行8次(默认值),一次只回收掉部分Region,然后系统继续运行一小段时间,之后再继续混合回收,重复8轮。混合回收通过间断操作,可以把每次的回收时间控制在指定的停顿时间之内,最终也达到了垃圾清理的效果。
-XX:G1MixedGCCountTarget=8
#混合回收整理出来的空闲空间占heap的5%时(默认值),终止本次回收
-XX:G1HeapWastePercent=5

#如果一个Region中的存活对象大于Region大小的85%的话(默认值),就不去回收这个Region
-XX:G1MixedGCLiveThresholdPercent=85

#设置新生代大小,默认5%,默认最大60%。在运行过程中,JVM会不停的给年轻代增加更多的Region,但是最多新生代的占比不会超过G1MaxNewSizePercent值
#年轻代中的Eden和Survivor对应的region也跟之前 一样,默认8:1:1,例如年轻代现在有1000个region,eden区对应800个,s0对应100个,s1对应 100个
#理论上,不同的应用、不同的CPU硬件资源,都会有不同的最优值,但区别不会太大。通过实践总结,调整该值的收益远不如调整其他参数(如上面提到的几个)
-XX:G1NewSizePercent=5 -XX:G1MaxNewSizePercent=60

 #gc日志打印到执行日志文件
-Xloggc:/data/server/${app}/gc.log
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime 

#可以生成更详细的Survivor空间占用日志,开发环境调试用
-XX:+PrintAdaptiveSizePolicy 
#在控制台输出GC情况,一般是本地调试用。(上线后是后台运行,不关注控制台日志)
-verbose:gc 

#开启远程debug,开发环境、测试环境可考虑配置
-Xdebug -Xrunjdwp:transport=dt_socket,address=9555,server=y,suspend=n 

#spring相关,指定加载配置文件
--spring.config.location=classpath:/,classpath:/config/,file:./,file:./config/,file:/home/mall-job/conf/

示例1、高并发系统jvm参数配置
-Xms8g -Xmx8g
-XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:G1HeapRegionSize=8m -XX:G1MixedGCCountTarget=8
-Xloggc:/data/server/${app}/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime

示例2、高响应系统jvm参数配置示例(尽量提高业务吞吐量),核心思想:通过控制Region的大小,从而加快单个Region的回收耗时
-Xms2g -Xmx2g
-XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:G1HeapRegionSize=1m -XX:G1MixedGCCountTarget=10
-Xloggc:/data/server/${app}/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime

备注:其他JVM参数(-XX)

#新时代E区和S区比例,默认8:1:1。一般来说,不需要调整
-XX:SurvivorRatio=8 

#异常场景相关参数 
-XX:ErrorFile=文件 设置错误日志路径 -XX:ErrorFile=./hs_err_pid%p.log %p为当前进程号
-XX:OnError=命令 错误发生时执行命令 -XX:OnError="gcore %p;dbx - %p"
-XX:OnOutOfMemoryError=命令 内存溢出时执行命令
-XX:MaxDirectMemorySize=size 设置直接内存最大值 -XX:MaxDirectMemorySize=100m 默认为0 当直接内存达到设置的最大值会FullGC
-XX:ObjectAlignmentInBytes=alignment 设置java对象的内存对齐,默认是8字节
-XX:ThreadStackSize 设置线程栈大小 -XX:ThreadStackSize=1m = -Xss
-XX:-UseBiasedLocking 禁用偏向锁 默认开启,不禁用 如果使用的是大量的没有竞争的同步,使用偏向锁会提升性能
-XX:-UseCompressedOops 禁用压缩指针堆内存小于32G时默认开启 开启后,对象引用是32位而不是64位,可以提升性能。只有64位的jvm才生效
-XX:+DoEscapeAnalysis 开启逃逸分析 默认开启
-XX:+Inline 开启方法内联 默认开启
-XX:InlineSmallCode=大小 设置应内联的已编译方法的最大代码大小,只有小于此数值的才会内联 默认1000字节
-XX:MaxInlineSize=大小 设置要内联方法的最大字节码大小 默认35字节
-XX:+OptimizeStringConcat 开启字符串连接优化 默认开启
-XX:+PrintInlining 打印方法内联 默认关闭,需和-XX:+UnlockDiagnosticVMOptions 一起使用
-XX:-TieredCompilation 关闭分层编译 默认开启
-XX:+HeapDumpOnOutOfMemoryError  OOM时堆内存dump到当前目录
-XX:HeapDumpPath=路径 设置堆内存dump的路径 -XX:HeapDumpPath=/var/java_pid%p.hprof
-XX:+UnlockDiagnosticVMOptions 开启jvm诊断功能选项

#垃圾回收相关参数
-XX:+AggressiveHeap 开启堆最优化设置 默认关闭
-XX:+CMSClassUnloadingEnabled 当使用CMS垃圾收集器时,允许类卸载 默认开启
-XX:CMSExpAvgFactor=percent 指定垃圾收集消耗的时间百分比 默认这个数是25%,就是25
-XX:CMSInitiatingOccupancyFraction=percent 设置CMS回收开始的老年代百分比 默认-1,任何的负值表示会使用-XX:CMSTriggerRatio选项来定义这个百分比数
-XX:+CMSScavengeBeforeRemark 在CMS重新标记之前执行ygc操作  默认关闭 在remark时间过长时可以开启;开启减少remark的STW时间
-XX:CMSTriggerRatio=percent 设置CMS开始的百分比 默认80,((100 - MinHeapFreeRatio) + (double)( CMSTriggerRatio * MinHeapFreeRatio) / 100.0) / 100.0=92%
-XX:+UseCMSCompactAtFullCollection  在FULL GC的时候,对年老代的压缩
-XX:CMSFullGCsBeforeCompaction=0  上面配置开启的情况下,这里设置多少次Full GC后,对年老代进行压缩,
-XX:MinHeapFreeRatio=percent GC之后堆内存最小剩余百分比,如果小于此值,则自动扩容 默认40%
-XX:MaxHeapFreeRatio=percent GC之后堆内存最大剩余百分比,如果小于此值,则自动缩容 默认70%
-XX:ParallelGCThreads=threads 设置Parallel GC的线程数 默认根据cpu个数,<=8,则使用8个,>8个3+5N/81台服务器只有1个jvm时使用默认值较好,如果有n个jvm,cpu个数 / n比较合适
-XX:ConcGCThreads=个数 并发GC的线程数 默认值取决于cpu个数 ConcGCThreads = (ParallelGCThreads + 3)/4
-XX:+DisableExplicitGC 使System.gc()显式gc失效 默认不开启,
-XX:G1HeapRegionSize=size 当使用G1收集器时,设置java堆被分割的region大小 1M~32M默认根据堆内存最优化设置
-XX:+G1PrintHeapRegions 打印G1收集器收集的区域  默认关闭
-XX:G1ReservePercent=percent  设置堆内存保留大小,以防晋升失败 0~50 默认10%
-XX:InitialHeapSize=size 堆初始大小 =-Xms
-XX:MaxHeapSize=size 堆最大大小 =-Xmx
-XX:InitialSurvivorRatio=ratio 设置伊甸园区和幸存区初始比例 默认为8:1
-XX:SurvivorRatio=ratio 设置伊甸园区和幸存区比例 默认为8:1  8:1:1
-XX:TargetSurvivorRatio YGC之后,幸存区期望百分比 默认 50%
-XX:InitiatingHeapOccupancyPercent=percent 堆占用达到多少开始并发垃圾回收 只有并发垃圾回收器生效
-XX:MaxGCPauseMillis=time GC最大暂停时间 ms 默认没有最大暂停时间
-XX:MetaspaceSize=size 元空间多次扩容后超过此值就会full gc 默认大约20M 元空间使用本地内存。 尽量设置足够,避免因为这个区域内存不够引发Full GC
-XX:MaxMetaspaceSize=size 设置元空间最大大小 默认不限制 建议和MetaspaceSize一样大,一般256M
-XX:NewSize=size 设置年轻代初始大小 建议年轻代占堆大小的1/4 ~ 1/2
-XX:MaxNewSize=size 设置年轻代最大大小 默认根据最大效能分配
-XX:MaxTenuringThreshold=threshold 最大晋升年龄,从年轻代到老年代 默认:15 - 并行回收器 6 - CMS
-XX:NewRatio=ratio 设置老年代和新生代比例 默认2 老年代 : (伊甸园 + 2个幸存区)
-XX:+PrintGC 打印GC信息 默认关闭
-XX:+PrintGCDetails 打印GC详细信息 默认关闭
-XX:+PrintTenuringDistribution 打印晋升分配
-XX:+ScavengeBeforeFullGC Full gc之前先ygc 默认开启
-XX:+UseTLAB 年轻代使用线程局部缓存 默认开启  效率高
-XX:TLABSize=size 设置初始化thread-local allocation buffer (TLAB)大小
-XX:+UseAdaptiveSizePolicy  JDK 1.8 默认使用 UseParallelGC 垃圾回收器,该垃圾回收器默认启动了 AdaptiveSizePolicy
-XX:+UseParallelGC 年轻代使用并行回收器
-XX:+UseParallelOldGC 老年代使用并行回收器
-XX:+UseParNewGC 为配置CMS,年轻代使用ParNew回收器,CMS会默认开启
-XX:+UseConcMarkSweepGC 使用CMS回收器
-XX:+UseG1GC 使用G1回收器
-XX:+UseGCOverheadLimit 限制GC的运行时间,通过统计GC时间来预测是否要OOM了,提前抛出异常,防止OOM发生 并行/并发回收器在GC回收时间过长时会抛出OutOfMemroyError。过长的定义是,超过98%的时间用来做GC并且回收了不到2%的堆内存。用来避免内存过小造成应用不能正常工作
-XX:+UseStringDeduplication 开启字符串去重 G1回收器生效
-XX:AutoBoxCacheMax=20000 加大Integer Cache
-XX:+PrintPromotionFailure 知道是多大的新生代对象晋升到老生代失败从而引发Full GC时的。

补充:G1工作过程简述

G1垃圾回收器的运行过程大致可划分为以下四个步骤:

初始标记(initial mark),标记了从GC Root开始直接关联可达的对象。STW(Stop the World)执行。
并发标记(concurrent marking),和用户线程并发执行,从GC Root开始对堆中对象进行可达性分析,递归扫描整个堆里的对象图,找出要回收的对象
最终标记(Remark),STW,标记再并发标记过程中产生的垃圾。
筛选回收(Live Data Counting And Evacuation),制定回收计划,选择多个Region 构成回收集,把回收集中Region的存活对象复制到空的Region中,再清理掉整个旧 Region的全部空间。需要STW。

G1的垃圾回收流程主要是从新生代回收开始,新生代回收与并发标记再到混合回收,因此G1的垃圾回收也有阶段性的特点。
G1 Yong Collection
当Eden区域装满时会触发新生代的GC,系统会进入“Stop the World”状态,然后将标记存活的对象移动至Survivor区,达到晋升年龄的就晋升到老年代区域,然后清空原区域(不过这里可没有年轻代复制算法中两个Survivor的交换过程)。
此时G1 会选择把所有的年轻代区域加入回收集合中,但是为了满足用户停顿时间的配置,在每次GC后会调整这个最大年轻代区域的数量,每次回收的区域数量可能是变化的。

G1 Yong Collection + Concunrrent Mark
当G1新生代垃圾回收结束后,紧接着开始进入并发标记阶段:从GC Root开始对堆中对象进行可达性分析,递归扫描整个堆里的对象图,找出要回收的对象,这阶段耗时较长,但可与用户程序并发执行。

G1 Mixed Collection
当老年代的大小占据了堆内存的45%的Region时(-XX:InitiatingHeapOccupancyPercent的默认值是45%),此时就会触发一个新生代和老年代的混合回收阶段,对E S 0 H区进行全面回收。

Full GC
当在进行混合回收的过程中,由于无论是新生代还是老年代都是基于复制算法进行的,都需要将各个Region中的存活对象拷贝到别的Region中,此时如果一旦出现拷贝的过程中发现没有空闲的Region可以进行存储了,就会触发一次失败!那么这个时候系统会立马切换为我们的Seiral收集器进行单线程的标记、清理和压缩整理,该过程就变得非常的慢了!

标签:G1,Region,回收,XX,调优,GC,默认,JVM
From: https://www.cnblogs.com/yu007/p/17900844.html

相关文章

  • JVM内存参数的学习之三
    JVM内存参数的学习之三背景研究启动性能时,顺便看到了jmap-heap1的部分信息看到:MinHeapFreeRatio、MaxHeapFreeRatio自己突然以为是Percentage的参数,恍惚了好久.才发现自己对内存的学习不够,所以想多学习一下.参数解释MinHeapFreeRatio:空闲堆空间的最小......
  • nginx调优-调大rlimit_nofile
    前言对于Linux用户或用户组打开的进程,Linux系统会对进程可占用的资源进行限制。该限制针对特定Linux用户或用户组,限制范围是该Linux用户或用户组打开的所有进程。遇到的异常nginx转发的流量比较大。因此在nginx.conf中,存在如下配置:worker_rlimit_nofile131072;event{......
  • JVM虚拟机系统性学习-JVM相关工具jps、jstat、jinfo、jmap、jhat和jstack
    JVM相关工具JDK工具包jps查看Java进程jps:列出Java程序进程ID和Main函数名称jps-q:只输出进程IDjps-m:输出传递给Java进程(主函数)的参数jps-l:输出主函数的完整路径jps-v:显示传递给Java虚拟机的参数jstat查看Java程序运行时相关信息,可以查看运行时堆的相关情况jstat......
  • JVM垃圾回收机制
    JVM垃圾回收机制JVM垃圾回收机制术语回收机制:在Java中,程序员是不需要显示的去释放一个对象的内存的,而是由虚拟机自行执行。在JVM中,有一个垃圾回收线程,它是低优先级的,在正常情况下是不会执行的,只有在虚拟机空闲或者当前堆内存不足时,才会触发执行,扫描那些没有被任何引用的对象,并将......
  • JVM类加载机制
    JVM类加载机制类加载机制概念概念说明:1)虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验,解析和初始化,最终形成可以被虚拟机直接使用的Java类型。程序主动使用某个类时,如果该类还未被加载到内存中,则JVM会通过加载(loading)、连接(linking)、初始化(initialization)3个步骤......
  • JVM内存模型
    JVM内存模型JDK7堆内存模型内存模型说明:1)Young(新生代)Young区被划分为三部分,Eden(ˈiːdn)区和两个大小严格相同的Survivor(sərˈvaɪvər)区,其中Survivor区间中,某一时刻只有其中一个是被使用的,另外一个留做垃圾收集时复制对象用,在Eden区间变满的时候,GC就会将存活的对象移到空闲......
  • JVM虚拟机系统性学习-垃圾回收器CMS、G1和ZGC
    CMS:低延迟在JDK1.5时,HotSpot推出了CMS收集器,CMS收集器是HotSpot虚拟机中第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程和用户线程同时工作CMS收集器关注尽可能地降低用户线程的停顿时间,停顿时间越短,用户的体验越好CMS收集器采用标记-清除算法和STW机制来回......
  • JVM初了解
    一、JVM常用启动参数说明以-开头为标准参数,所有的JVM都要实现这些参数,并且向后兼容,如-server。-D设置系统属性,如-Dfile.encoding=UTF-8。以-X开头为非标准参数,基本都是传给JVM的,默认JVM实现这些参数的功能,但是并不保证所有JVM实现都满足,且不保证向后兼容......
  • 《深入浅出Java虚拟机:JVM原理与实战》
    ......
  • 使用jvm工具排查系统问题
    java-jvm-toolJstatd远程连接(推荐)不用重启项目远程机配置[demo@localhost jvmtest]$ vi jstatd.all.policy# 内容grant codebase "file:/home/demo/jdk1.8.0_171/lib/tools.jar" {permission java.security.AllPermission;};#IP为远程机外网IP(必须配置ip地址)[demo@l......