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

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
注册配置 MSE Nacos/ZooKeeper,118元/月
云原生网关 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异步小王子

相关文章
|
7天前
|
编解码 Java 程序员
写代码还有专业的编程显示器?
写代码已经十个年头了, 一直都是习惯直接用一台Mac电脑写代码 偶尔接一个显示器, 但是可能因为公司配的显示器不怎么样, 还要接转接头 搞得桌面杂乱无章,分辨率也低,感觉屏幕还是Mac自带的看着舒服
|
9天前
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
1570 10
|
1月前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
14天前
|
存储 人工智能 开发工具
AI助理化繁为简,速取代码参数——使用python SDK 处理OSS存储的图片
只需要通过向AI助理提问的方式输入您的需求,即可瞬间获得核心流程代码及参数,缩短学习路径、提升开发效率。
1035 1
AI助理化繁为简,速取代码参数——使用python SDK 处理OSS存储的图片
|
14天前
|
人工智能 Serverless API
AI助理精准匹配,为您推荐方案——如何快速在网站上增加一个AI助手
通过向AI助理提问的方式,生成一个技术方案:在网站上增加一个AI助手,提供7*24的全天候服务,即时回答用户的问题和解决他们可能遇到的问题,无需等待人工客服上班,显著提升用户体验。
1008 4
|
13天前
|
人工智能 Rust Java
10月更文挑战赛火热启动,坚持热爱坚持创作!
开发者社区10月更文挑战,寻找热爱技术内容创作的你,欢迎来创作!
798 27
|
1天前
|
人工智能 关系型数据库 Serverless
1024,致开发者们——希望和你一起用技术人独有的方式,庆祝你的主场
阿里云开发者社区推出“1024·云上见”程序员节专题活动,包括云上实操、开发者测评和征文三个分会场,提供14个实操活动、3个解决方案、3 个产品方案的测评及征文比赛,旨在帮助开发者提升技能、分享经验,共筑技术梦想。
429 44
|
7天前
|
并行计算 PyTorch TensorFlow
Ubuntu安装笔记(一):安装显卡驱动、cuda/cudnn、Anaconda、Pytorch、Tensorflow、Opencv、Visdom、FFMPEG、卸载一些不必要的预装软件
这篇文章是关于如何在Ubuntu操作系统上安装显卡驱动、CUDA、CUDNN、Anaconda、PyTorch、TensorFlow、OpenCV、FFMPEG以及卸载不必要的预装软件的详细指南。
502 3
|
2天前
|
移动开发 JavaScript 前端开发
💻揭秘!如何用 Vue 3 实现酷炫的色彩魔方游戏✨
本文分享了开发基于Canvas技术的小游戏"色彩魔方挑战"的完整过程。游戏旨在考验玩家的观察力和耐心,通过随机生成的颜色矩阵和一个变化点,玩家需在两幅画布中找出不同的颜色点。文章详细讲解了游戏的核心功能,包括随机颜色矩阵生成、点的闪烁提示、自定义配色方案等。此外,作者展示了使用Vue 3和TypeScript开发的代码实现,带领读者一步步深入了解游戏的逻辑与细节。
105 68
|
16天前
|
Linux 虚拟化 开发者
一键将CentOs的yum源更换为国内阿里yum源
一键将CentOs的yum源更换为国内阿里yum源
874 5