• (针对 G1 )JVM常用参数讲解:-XX,-X,-D 的区别与常用JVM配置 +应用程序配置实例+ 调优思路


    通过整体学习JVM参数以及一个应用所需要配置的JVM参数,可以了解项目运行时要配置那些JVM、并根据运行时特性和环境,进行JVM参数调优。

    一. JVM主要参数一览

    1. -XX开头:JVM规范中规定的参数

    -XX开头的配置是JVM都支持的配置

    参数类型:

    1. bool类型的配置:+开启、-关闭
    2. 键值型的配置:等号赋值

    1.1. 日志相关

    序号参数说明
    1-XX:+PrintGC打印简单GC日志
    2-XX:+PrintGCDetails打印详细GC日志
    3-XX:+PrintGCDateStamps显示每次GC的日期时间
    4-XX:+UseGCLogFileRotationGC日志文件循环使用(比如,5个日志文件循环使用)
    5-XX:GCLogFileSize=100M每个GC日志文件的默认大小
    6-XX:NumberOfGCLogFiles=5GC日志文件数,可以设置循环使用
    7-XX:-OmitStackTraceInFastThrow关闭栈异常信息快速抛出,从而记录详细的栈异常以便跟踪。
    8-XX:HeapDumpPath=/opt/logs/appid指定导出堆信息时的路径或文件名(路径要存在)
    9-XX:+HeapDumpOnOutOfMemoryError出现内存溢出时,Dump出当前的内存快照

     

    1.2. JVM运行时内存区设置(一)

    (二)见 -x 参数设置

    序号参数说明
    1-XX:MetaspaceSize=128m元空间的初始大小,不断扩容并首次超过这个值时会进行FGC,JVM会动态调整这个值
    2-XX:MaxMetaspaceSize=256m元空间的最大值,超过最大值时会抛异常出来,加载的类越多,元空间使用的内存越多,元空间使用 Native Memory。
    3-XX:MinHeapFreeRatio=30指定空闲堆空间的最小百分比,如果实际空闲堆空间小于此值则需要对堆进行扩容 ,Xmx==Xms 的情况下无效
    4-XX:MaxHeapFreeRatio=50指定空闲堆空间最大百分比 ,如果实际空闲堆空间大于此值则需要对对堆空间进行缩容,Xmx==Xms 的情况下无效

     

    1.3. GC相关设置

    序号参数说明
    1-XX:+UseG1GC使用G1GC
    2-XX:MaxGCPauseMillis=200最大GC暂停时间,G1GC尽量保证软实时性;
    3-XX:ParallelGCThreads=4(在STW阶段工作的)最大并行GC线程数
    4-XX:ConcGCThreads=4(在非STW期间的GC工作线程数)最大并发GC线程数

     
    -XX:MaxGCPauseMillis 解释

    这是一个软性目标,G1会尽量达成,如果达不成,会逐渐做自我调整。
    对于Young GC来说,会逐渐减少Eden区个数,减少Eden空间那么Young GC的处理时间就会相应减少;
    对于Mixed GC,G1会调整每次Choose Cset的比例,默认最大值是10%,当然每次选择的Cset少了,所要经历的Mixed GC的次数会相应增加。
    同时减少Eden的总空间时,就会更加频繁的触发Young GC,也就是会加快Mixed GC的执行频率,因为Mixed GC是由Young GC触发的,或者说借机同时执行的。
    
    
    频繁GC会对对应用的吞吐量造成影响,每次Mixed GC回收时间太短,回收的垃圾量太少,可能最后GC的垃圾清理速度赶不上应用产生的速度,那么可能会造成串行的Full GC,这是要极力避免的。所以暂停时间肯定不是设置的越小越好.
    
    当然也不能设置的偏大,这样可能会导致一次全部并发标记后触发的Mixed GC次数变少,但每次的时间变长,STW时间变长,对应用的影响更加明显。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

     

    1.4. JVM 调优参数

    序号参数说明
    1-XX:+AlwaysPreTouchjvm启动的时候分配物理内存
    2-XX:+ScavengeBeforeFullGCFull gc前先执行Minor gc
    3-XX:+DisableExplicitGC禁止显式执行GC,不允许通过代码来触发GC。
    4-XX:InitiatingHeapOccupancyPercent=70
    1. 当整个堆占用超过某个百分比时,就会触发并发GC周期;
    2. 如果项目没有大的cpu负载压力,可以适当降低这个值,带来的好处就是提前开始Concurrent Marking Cycle Phases,年轻代/老年代回收也会提前开始,这样有利于防止年轻代晋升老年代失败(老年代容量不足)而触发Full GC;
    5-XX:+UseTLAB开启线程专用内存分配区域

    -XX:+UseTLAB

    TLAB的全称是Thread Local Allocation Buffer,即线程分配缓存区。
    
    由于对象一般会分配在堆上,而堆是全局共享的。所以在同一时间,可能会有多个线程在堆上申请空间。
    而每次对象分配都必须要进行同步,在竞争激烈的场合分配的效率又会进一步下降。
    
    JVM使用TLAB来避免多线程冲突,在给对象分配内存时,每个线程使用自己的TLAB,这样可以避免线程同步。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

     

    2. -X 开头:HotSpot支持的参数

    -X 开头特用于java HotSpot虚拟机的通用选项

    JVM运行时内存区设置(二) + 日志设置

    序号参数说明
    1-Xmx2gJVM 最大堆内存
    2-Xms2gJVM 初始堆内存。通常这两个配置参数相等,避免每次空间不足,动态扩容带来的影响。
    3-Xss256k设置每个线程的栈大小
    4-Xloggc:$APP_LOG_DIR/gc-%t.loggc日志生成目录

     

    3. -D :系统参数(系统默认或自定义)

    在启动一个java程序时设置的系统属性,参数会在jvm启动java应用程序之前赋值给应用程序
    也可以通过使用System.setProperty(key, value)来完成。

     -Djava.util.concurrent.ForkJoinPool.common.parallelism=480
     -DdodpPipelineWorker.main.class=${MAIN_CLASS}
     -Dconfig=$APP_HOME/config
     -Dfile.encoding=UTF-8
     -Dspring.liquibase.enabled=false
     -Ddubbo.application.logger=log4j2
     -Dlogging.config=${APP_HOME}/config/log4j2.xml
     -DcwAppHome=${APP_HOME}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

     
     

    二、相关计算和说明

    1. 堆的讨论

    堆的计算

    整个堆大小的计算公式: JVM 堆大小 = 年轻代大小+年老代大小+持久代大小。
     
    增大新生代大小就会减少对应的老年代大小,设置-Xmn值对系统性能影响较大,所以如果设置新生代大小的调整,则需要严格的测试调整。

    相关经验

    1. Xmn用于设置新生代的大小。过小会增加Minor GC频率,过大会减小老年代的大小。一般设为整个堆空间的1/4或1/3.
    2.一般来说,MaxPermSize设为64MB可以满足绝大多数的应用了。若依然出现方法区溢出,则可以设为128MB。若128MB还不能满足需求,那么就应该考虑程序优化了,减少动态类的产生。
    3. 当Xms=Xmx,可以使得堆相对稳定,避免不停震荡

     

    2. JVM GC相关参数

    2.1. 垃圾回收算法回顾

    1. 引用计数法: 会有循环引用的问题,不推荐;
    2. Mark-Sweep: 标记清除。根可达判断,最大的问题是产生空间碎片;
    3. Copying: 复制算法。对于短命对象来说有用,否则需要复制大对象,效率低。如Java的新生代堆空间中就是使用了它(survivor空间的from和to区);
    4. Mark-Compact: 标记整理。对于老年对象来说有用,无需复制,不会产生内存碎片

    2.2. GC 时要考虑的指标

    吞吐量:应用耗时和总运行耗时的比值;
    停顿时间:垃圾回收的时候,由于Stop the World,应用程序的所有线程会挂起,造成应用停顿。

    吞吐量和停顿时间是成反比的

    • 对于后端服务:吞吐量优先考虑(推荐:并发垃圾回收)
    • 对于前端应用:响应时间优先考虑,减少STW时间(推荐:并发垃圾回收)

     
     

    三、应用程序配置示例

    JVM_OPTS="
    # server模式 + 堆 、栈大小
     -server
     -Xms${ENV_JVM_HEAP_SIZE:-${INNER_JVM_HEAP_SIZE_MIN}}
     -Xmx${ENV_JVM_HEAP_SIZE:-${INNER_JVM_HEAP_SIZE_MAX}}
     -Xss256k 
    
    
    # 相关调优设置                                        
     -XX:+AlwaysPreTouch
     -XX:+UseG1GC
     -XX:MaxGCPauseMillis=200
     -XX:InitiatingHeapOccupancyPercent=70                  
     -XX:+ScavengeBeforeFullGC
     -XX:+DisableExplicitGC
     
     
     #日志相关
     -XX:+PrintGCDetails
     -XX:+PrintGCDateStamps
     -XX:+UseGCLogFileRotation
     -XX:NumberOfGCLogFiles=5
     -XX:GCLogFileSize=100m
     -Xloggc:$APP_LOG_DIR/gc-%t.log
     -Xbootclasspath/a:$APP_HOME/config
     
     
     #程序参数
     -Djava.util.concurrent.ForkJoinPool.common.parallelism=480
     -DdodpPipelineWorker.main.class=${MAIN_CLASS}
     -Dconfig=$APP_HOME/config
     -Dfile.encoding=UTF-8
     -Dspring.liquibase.enabled=false
     -Ddubbo.application.logger=log4j2
     -Dlogging.config=${APP_HOME}/config/log4j2.xml
     -DcwAppHome=${APP_HOME}
    "
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
  • 相关阅读:
    Redis内存回收
    一篇文章带你走进cookie,session,Token的世界
    这两天搭建环境遇到的几个问题
    2022年全球市场香兰素总体规模、主要生产商、主要地区、产品和应用细分研究报告
    【vscode】vscode在离线环境下配置远程服务器客户端
    【吃瓜之旅】第三章吃瓜学习
    Redis中是如何实现分布式锁的?
    spring cloud gatewa修改路由等信息
    【WINDOWS / DOS 批处理】IF命令之比较运算符证明实例
    C++可调用对象的绑定器和包装器
  • 原文地址:https://blog.csdn.net/hiliang521/article/details/126419882