JVM进阶调优系列(6)一文详解JVM参数与大厂实战调优模板推荐

本文涉及的产品
注册配置 MSE Nacos/ZooKeeper,118元/月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
云原生网关 MSE Higress,422元/月
简介: 本文详述了JVM参数的分类及使用方法,包括标准参数、非标准参数和不稳定参数的定义及其应用场景。特别介绍了JVM调优中的关键参数,如堆内存、垃圾回收器和GC日志等配置,并提供了大厂生产环境中常用的调优模板,帮助开发者优化Java应用程序的性能。

读书心得:乐观积极面对挑战,能力与挑战难度相匹配,专注享受当下事宜,无视周边因素,达到忘我状态,时间也会忘记。

    不管是刚入行没多久的JAVA初级级研发还是10年资深架构师,手上都需要珍藏一份JVM参数指南。不仅是为了学习JVM调优,也是时刻方便在实际工作中对业务系统的调优监控做出及时调整。本文全面整理JVM参数清单,并做成表格,以及公开一份大厂生产环境核心常用的调优模板供大家参考应用,希望对有缘刷到的同学有所帮助。

    上一篇文章,末尾我们给了一份jvm参数清单并留了一个问题,说说每个参数的意义?看完本文就能得到完整的答案(坚持授人以鱼,不如授人以渔的原则),尽量不填鸭投喂,希望和大家一起思考提升进步。

一、JVM参数有多少种类型?

    这个分类没有标准答案,大家根据各自理解和应用,会有不同分类。我们采用从参数开头、区域功能类型两大类进行划分,更加贴近实际应用,也方便记忆和学习。

二、按参数开头划分

    首先,大家看一下这份jar包启动参数命令集,先不用想具体含义,看看参数都有哪些特点。

    这里看到里面有的是-X开头,有的是-XX开头,有的是-D开头,有的是-开头。这里我们把-开头的,叫做【标准参数】,-X开头的叫做【非标准参数】,-XX开头的叫做【非稳定参数】。

2.1 标准参数(-开头)

    -开头的标准参数,我们常见的有:-jar,-help,-version,以及-agentpath:[=<选项>]、-javaagent:[=<选项>]都是。

2.1.1 如何查看全部标准参数列表?

    可以通过java -help命令去查看标准参数清单。

2.2 非标准参数(-X开头)

    -X开头的非标准参数,随着JDK的版本变化,参数的变化也很少。这里就有很多熟悉的参数,具体参数含义我们在文末表格里详细说明。这里简略说几个,比如以下三个。

-Xms :设置初始 Java 堆大小;
-Xmx  :设置最大 Java 堆大小;
-Xss   设置 Java 线程堆栈大小;

2.2.1 那如何查看-X开头的非标准参数,如何整理全部JVM参数清单?

    其实也简单,类似非标准参数java -help一样,只要执行java -X 就可以看到全部非标准参数。

2.3 不稳定(UnStable)参数(-XX开头)

     我们常说的JVM调优,应用最多的就是这个-XX开头的参数,它也是最为复杂。而且不同JDK版本、应用不同的垃圾回收器参数都各不相同,非常值得我们深入学习探讨。这些非稳定参数,有的用来选择GC回收器类型、有的用来控制GC日志、有的用来控制GC频率、内存占比划分。比如:


设置年老年用CMS垃圾回收器的-XX:+UseConcMarkSweepGC;
设置年轻代存活对象进入老年代的年龄-XX:MaxTenuringThreshold=10 
设置打印GC日志 -XX:+PrintGC。

    这里发现,不稳定参数的赋值语法还有点复杂,这里细分了几种类型。

2.3.1 不稳定参数赋值语法

1、数字类型参数值

    -XX:=,用=号并赋值数字。

    比如,-XX:SurvivorRatio=8,这个8是JDK的默认值。标识年轻代中Eden区大小/两个Survivor区的大小。也就是在年轻代内存划分,默认比例是Eden:S1:S0 = 8:1:1。

2、布尔类型参数值

    是通过+\-号,来表示启用、禁用。

-XX:+

-XX:-

    比如,刚才这个-XX:+UseConcMarkSweepGC,表示启用CMS垃圾收集器。

3、字符串类型参数值

    通过=并设置字符串值。

-XX:=

    比如:-XX:HeapDumpPath=./log/dump/oom.log,设置内存溢出快照保存地址。

2.3.2 那如何查看全部JVM -XX开头的参数呢?

    之前是java -X查看非标准参数,现在是 java -XX?

(base) MacBook-Pro ~ % java -XX
Unrecognized option: -XX
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.

报错了,不能如此类推!这里末尾还需要加+PrintFlagsFinal才可以。

java -XX:+PrintFlagsFinal

三、按区域功能划分

    之前我们的文章系列2《JVM内存区域怎么划分,分别有什么用》有详细说过内存区域划分,里面有堆内存(分年轻代和老年代)、MetaSpace元数据区、虚拟机栈、程序计数器、系统直接内存几个区。老话长谈JVM调优,主要就是对堆内存GC进行调优。所以有必要专门了解整理堆内存相关参数。

3.1 堆内存相关参数

    我们这里把虚拟机栈、堆内存,MetaSpace元数据区相关参数都统一当做堆内存参数。除了刚才说的非标准参数-Xms、-Xmx、-Xmn,还有:

-XX:NewRatio=n,设置年轻代和年老代的比值为n;
-Xss,设置每个线程堆栈大小;
-XX:MaxMetaspaceSize 设置元数据区大小。

3.2 垃圾回收器参数

    与GC垃圾回收器相关的参数,我们划为一类。比如:

-XX:CMSFullGCsBeforeCompaction,CMS回收器完成多少次FGC后进行内存压缩;
-XX:CMSInitiatingOccupancyFraction=92,老年代占比大于92%后开始CMS FGC处理
-XX:+UseParNewGC,使用ParNew回收器来为年轻代做YGC;
-XX:ParallelGCThreads,负责垃圾回收的并发线程数量。

3.3 GC日志、OOM相关参数

    GC日志控制、OOM相关后置处理参数,划为一类。比如:

-XX:GCLogFileSize=n,GC log 滚动大小;
-Xloggc:log/myapp_gc.log,发生gc后相关gc日志保存;
-XX:+HeapDumpOnOutOfMemoryError ,内存溢出时导出整个堆信息,让JVM遇到OOM异常时能输出堆内信息;
-XX:HeapDumpPath=./oomlog/dump/,内存异常堆数据导出地址。

四、大厂生产调优实践参数模板

    在一线头部大厂,通过长期生产实践技术经验积累,基础技术架构组或者相关架构师会整理分享一个jvm最佳实践模板,帮助团队成员根据不同的业务场景快速调整出一份适合自己系统服务的JVM参数。让核心服务首次上线、以及后续业务规模增长,不管监控是否发现性能问题、还是业务爆涨,都能提供长期稳定运行支撑。

    这里分享一份生产实战调优常用(也可以说是必用的核心参数)的一个模板,大家不可盲目照搬直接应用,可以先保存,具体还是要看业务量、业务场景来调整,后续分享实战案例,帮助大家分析选择调优自己的系统服务。

-Xms8888M -Xmx8888M -Xmn6666M -Xss1M -XX:MetaspaceSize=256M 
-XX:MaxMetaspaceSize=256M 
-XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=10
-XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFaction=92
-XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=2 
-XX:+CMSParallelInitialMarkEnabled
XX:+CMSScavengeBeforeRemark -XX:+PrintGCApplicationStoppedTime 
-XX:+DisableExplicitGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps
-Xloggc:gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/mycompany/appname/oom

    这个模板,有些参数是非常必要的,比如:

-XX:+DisableExplicitGC: 关闭System.gc(),程序代码里主动gc是非常糟糕的。
-XX:+CMSParallelInitialMarkEnabled:CMS的初始标记阶段是会Stop the world,导致系统停顿,
加了这个参数可以开启多线程并发进行标记,减少暂停时间。
-XX:CMSScavengeBeforeRemark:CMS的重新标记阶段也是会Stop the world,打开这个参数好处,
就是可以在【重新标记】之前先执行YGC,YGC会回收没有再被年轻代引用的对象。
这样重新标记阶段就可以少扫描一些对象,提高CMS重新标记阶段的性能。

   其他几个,大家看第四部分参数清单去找对应含义和重要性。现附上JVM参数表格。

五、JVM参数详解说明表格

    粗略统计了一下,JDK8 JVM全部参数加起来有将近800个,实际我们常用的以及调优参数大概100多个,这里我们重点列举核心常用的参数。

参数名

参数意义、用法说明

默认值

-Xms

设置初始 Java 堆大小

-Xmx

堆内存可以扩展到最大大小

-Xmn

堆内存里年轻代的大小

默认是8

-Xss

线程堆栈大小,单位是:k或K,表示KB;m或M表示MB;g或G表示GB;

-Xnoclassgc

禁用类的GC垃圾收集

-Xincgc

启用增量垃圾收集

-Xcheck:jni

对 JNI 函数执行其他检查

-Xbatch

禁用后台编译

-Xloggc

指定GC日志路径,-Xloggc:/data/gclog/mygc.log

-Duser.timezone

指定时区

-XX:MaxMetaspaceSize

元数据区最大大小,这个地方放.class类信息

-XX:MetaspaceSize

类元数据区的大小,Metaspace第一次超出该大小时触发垃圾回收。

-XX:ThreadStackSize

线程堆栈大小

默认值1024

-XX:NewRatio

年轻代与年老代的比值,默认是2:1

默认值2

-XX:MaxTenuringThreshold

年轻代对象进入老年代的年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。

默认是15

-XX:LargePageSizeInBytes

内存页大小

-XX:PretenureSizeThreshold

可以直接进入老年代的大对象大小

-XX+BackgroundCompilation

启用后台编译。默认启用。如果禁用,则-XX:-BackgroundCompilation。

XX:+DisableExplicitGC

禁用System.gc()

默认是禁用

-XX:SurvivorRatio

Eden区与Survivor区的大小比值

默认是8,E:S1:S0=8:1:1

-XX: +PrintGCApplicationStoppedTime

打印应用程序由于GC而产生的停顿时间

-XX:ConcGCThreads

并发GC的线程数

-XX:ParallelGCThreads

负责垃圾回收的并发线程数量

-XX:+AggressiveHeap

启用Java堆优化

默认禁用

-XX:CMSInitiatingOccupancyFraction

老年代占比大于该参数比例后开始CMS FGC处理(这个值大于等于0则直接取百分号,小于0则根据公式来计算。往往需要配合-XX:+UseCMSInitiatingOccupancyOnly使用)

默认92

-XX:+CMSScavengeBeforeRemark

打开这个参数,CMS在【重新标记】之前先执行YGC

-XX: +UseCMSInitiatingOccupancyOnly

打开这个参数后,CMS通过CMSInitiatingOccupancyFraction的值进行垃圾回收。

-XX:+UseParNewGC

使用ParNew垃圾收集器

-XX:+UseConcMarkSweepGC

指定使用CMS垃圾回收器

-XX:+CMSClassUnloadingEnabled

CMS垃圾收集器时启用类卸载

默认启用

XX:CMSFullGCsBeforeCompaction

多少次GC后,CMS进行内存碎片整理

-XX:+PrintGCDetails

打印GC详细信息

-XX:+PrintHeapAtGC

打印GC前后详细的堆栈信息

-XX:+PrintReferenceGC

跟踪系统内的软引用,弱引用,虚引用和Finallize队列

-XX:OnOutOfMemoryError=”“

指定这个参数,可以在服务OOM后,执行自定义脚本,比如用来发送邮件告警信息,重启服务。="/opt/local/bin/alert-restart.sh"

-XX:HeapDumpPath =

OOM抛出异常时,将堆数据转储到HeapDumpPath目录

-XX:+PrintGC

简单打印GC日志

-XX:+UseSerialGC

使用串行垃圾收集器

-XX:+UseG1GC

使用G1垃圾回收器

-XX:MaxGCPauseMillis

设置并行收集最大暂停时间

-XX:+ExplicitGCInvokesConcurrent

允许使用System.gc()请求调用并发GC

-XX:+UseGCOverheadLimit

限制OOM异常之前JVM在GC上花费的时间比例

默认启用

.............

推荐阅读:

1、JVM进阶调优系列(3)堆内存的对象什么时候被回收?

2、JVM进阶调优系列(2)字节面试:JVM内存区域怎么划分,分别有什么用?

3、JVM进阶调优系列(1)类加载器原理一文讲透

4、JAVA并发编程系列(13)Future、FutureTask异步小王子

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
8天前
|
NoSQL Java Redis
秒杀抢购场景下实战JVM级别锁与分布式锁
在电商系统中,秒杀抢购活动是一种常见的营销手段。它通过设定极低的价格和有限的商品数量,吸引大量用户在特定时间点抢购,从而迅速增加销量、提升品牌曝光度和用户活跃度。然而,这种活动也对系统的性能和稳定性提出了极高的要求。特别是在秒杀开始的瞬间,系统需要处理海量的并发请求,同时确保数据的准确性和一致性。 为了解决这些问题,系统开发者们引入了锁机制。锁机制是一种用于控制对共享资源的并发访问的技术,它能够确保在同一时间只有一个进程或线程能够操作某个资源,从而避免数据不一致或冲突。在秒杀抢购场景下,锁机制显得尤为重要,它能够保证商品库存的扣减操作是原子性的,避免出现超卖或数据不一致的情况。
41 10
|
17天前
|
监控 架构师 Java
Java虚拟机调优的艺术:从入门到精通####
本文作为一篇深入浅出的技术指南,旨在为Java开发者揭示JVM调优的神秘面纱,通过剖析其背后的原理、分享实战经验与最佳实践,引领读者踏上从调优新手到高手的进阶之路。不同于传统的摘要概述,本文将以一场虚拟的对话形式,模拟一位经验丰富的架构师向初学者传授JVM调优的心法,激发学习兴趣,同时概括性地介绍文章将探讨的核心议题——性能监控、垃圾回收优化、内存管理及常见问题解决策略。 ####
|
26天前
|
Java
JVM内存参数
-Xmx[]:堆空间最大内存 -Xms[]:堆空间最小内存,一般设置成跟堆空间最大内存一样的 -Xmn[]:新生代的最大内存 -xx[use 垃圾回收器名称]:指定垃圾回收器 -xss:设置单个线程栈大小 一般设堆空间为最大可用物理地址的百分之80
|
24天前
|
监控 Java 编译器
Java虚拟机调优指南####
本文深入探讨了Java虚拟机(JVM)调优的精髓,从内存管理、垃圾回收到性能监控等多个维度出发,为开发者提供了一系列实用的调优策略。通过优化配置与参数调整,旨在帮助读者提升Java应用的运行效率和稳定性,确保其在高并发、大数据量场景下依然能够保持高效运作。 ####
27 1
|
26天前
|
存储 算法 Java
JVM进阶调优系列(10)敢向stop the world喊卡的G1垃圾回收器 | 有必要讲透
本文详细介绍了G1垃圾回收器的背景、核心原理及其回收过程。G1,即Garbage First,旨在通过将堆内存划分为多个Region来实现低延时的垃圾回收,每个Region可以根据其垃圾回收的价值被优先回收。文章还探讨了G1的Young GC、Mixed GC以及Full GC的具体流程,并列出了G1回收器的核心参数配置,帮助读者更好地理解和优化G1的使用。
|
27天前
|
监控 Java 测试技术
Elasticsearch集群JVM调优垃圾回收器的选择
Elasticsearch集群JVM调优垃圾回收器的选择
48 1
|
1月前
|
监控 Java 编译器
Java虚拟机调优实战指南####
本文深入探讨了Java虚拟机(JVM)的调优策略,旨在帮助开发者和系统管理员通过具体、实用的技巧提升Java应用的性能与稳定性。不同于传统摘要的概括性描述,本文摘要将直接列出五大核心调优要点,为读者提供快速预览: 1. **初始堆内存设置**:合理配置-Xms和-Xmx参数,避免频繁的内存分配与回收。 2. **垃圾收集器选择**:根据应用特性选择合适的GC策略,如G1 GC、ZGC等。 3. **线程优化**:调整线程栈大小及并发线程数,平衡资源利用率与响应速度。 4. **JIT编译器优化**:利用-XX:CompileThreshold等参数优化即时编译性能。 5. **监控与诊断工
|
24天前
|
存储 IDE Java
实战优化公司线上系统JVM:从基础到高级
【11月更文挑战第28天】Java虚拟机(JVM)是Java语言的核心组件,它使得Java程序能够实现“一次编写,到处运行”的跨平台特性。在现代应用程序中,JVM的性能和稳定性直接影响到系统的整体表现。本文将深入探讨JVM的基础知识、基本特点、定义、发展历史、主要概念、调试工具、内存管理、垃圾回收、性能调优等方面,并提供一个实际的问题demo,使用IntelliJ IDEA工具进行调试演示。
25 0
|
27天前
|
缓存 Prometheus 监控
Elasticsearch集群JVM调优设置合适的堆内存大小
Elasticsearch集群JVM调优设置合适的堆内存大小
211 1
|
2月前
|
存储 安全 Java
jvm 锁的 膨胀过程?锁内存怎么变化的
【10月更文挑战第3天】在Java虚拟机(JVM)中,`synchronized`关键字用于实现同步,确保多个线程在访问共享资源时的一致性和线程安全。JVM对`synchronized`进行了优化,以适应不同的竞争场景,这种优化主要体现在锁的膨胀过程,即从偏向锁到轻量级锁,再到重量级锁的转变。下面我们将详细介绍这一过程以及锁在内存中的变化。
40 4
下一篇
DataWorks