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

本文涉及的产品
注册配置 MSE Nacos/ZooKeeper,118元/月
云原生网关 MSE Higress,422元/月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: 本文详述了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日志并进行多维度分析。
相关文章
|
16天前
|
Arthas 监控 Java
JVM进阶调优系列(9)大厂面试官:内存溢出几种?能否现场演示一下?| 面试就那点事
本文介绍了JVM内存溢出(OOM)的四种类型:堆内存、栈内存、元数据区和直接内存溢出。每种类型通过示例代码演示了如何触发OOM,并分析了其原因。文章还提供了如何使用JVM命令工具(如jmap、jhat、GCeasy、Arthas等)分析和定位内存溢出问题的方法。最后,强调了合理设置JVM参数和及时回收内存的重要性。
|
15天前
|
监控 Java 编译器
Java虚拟机调优实战指南####
本文深入探讨了Java虚拟机(JVM)的调优策略,旨在帮助开发者和系统管理员通过具体、实用的技巧提升Java应用的性能与稳定性。不同于传统摘要的概括性描述,本文摘要将直接列出五大核心调优要点,为读者提供快速预览: 1. **初始堆内存设置**:合理配置-Xms和-Xmx参数,避免频繁的内存分配与回收。 2. **垃圾收集器选择**:根据应用特性选择合适的GC策略,如G1 GC、ZGC等。 3. **线程优化**:调整线程栈大小及并发线程数,平衡资源利用率与响应速度。 4. **JIT编译器优化**:利用-XX:CompileThreshold等参数优化即时编译性能。 5. **监控与诊断工
|
25天前
|
存储 监控 Java
JVM进阶调优系列(8)如何手把手,逐行教她看懂GC日志?| IT男的专属浪漫
本文介绍了如何通过JVM参数打印GC日志,并通过示例代码展示了频繁YGC和FGC的场景。文章首先讲解了常见的GC日志参数,如`-XX:+PrintGCDetails`、`-XX:+PrintGCDateStamps`等,然后通过具体的JVM参数和代码示例,模拟了不同内存分配情况下的GC行为。最后,详细解析了GC日志的内容,帮助读者理解GC的执行过程和GC处理机制。
|
2月前
|
Arthas 监控 数据可视化
JVM进阶调优系列(7)JVM调优监控必备命令、工具集合|实用干货
本文介绍了JVM调优监控命令及其应用,包括JDK自带工具如jps、jinfo、jstat、jstack、jmap、jhat等,以及第三方工具如Arthas、GCeasy、MAT、GCViewer等。通过这些工具,可以有效监控和优化JVM性能,解决内存泄漏、线程死锁等问题,提高系统稳定性。文章还提供了详细的命令示例和应用场景,帮助读者更好地理解和使用这些工具。
|
2月前
|
存储 安全 Java
jvm 锁的 膨胀过程?锁内存怎么变化的
【10月更文挑战第3天】在Java虚拟机(JVM)中,`synchronized`关键字用于实现同步,确保多个线程在访问共享资源时的一致性和线程安全。JVM对`synchronized`进行了优化,以适应不同的竞争场景,这种优化主要体现在锁的膨胀过程,即从偏向锁到轻量级锁,再到重量级锁的转变。下面我们将详细介绍这一过程以及锁在内存中的变化。
38 4
|
14天前
|
Java Linux Windows
JVM内存
首先JVM内存限制于实际的最大物理内存,假设物理内存无限大的话,JVM内存的最大值跟操作系统有很大的关系。简单的说就32位处理器虽然可控内存空间有4GB,但是具体的操作系统会给一个限制,这个限制一般是2GB-3GB(一般来说Windows系统下为1.5G-2G,Linux系统下为2G-3G),而64bit以上的处理器就不会有限制。
14 1
|
2月前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
70 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
2月前
|
存储 缓存 算法
JVM核心知识点整理(内存模型),收藏再看!
JVM核心知识点整理(内存模型),收藏再看!
JVM核心知识点整理(内存模型),收藏再看!
|
2月前
|
存储 算法 Java
聊聊jvm的内存结构, 以及各种结构的作用
【10月更文挑战第27天】JVM(Java虚拟机)的内存结构主要包括程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区和运行时常量池。各部分协同工作,为Java程序提供高效稳定的内存管理和运行环境,确保程序的正常执行、数据存储和资源利用。
50 10
|
2月前
|
存储 算法 Java
Java虚拟机(JVM)的内存管理与性能优化
本文深入探讨了Java虚拟机(JVM)的内存管理机制,包括堆、栈、方法区等关键区域的功能与作用。通过分析垃圾回收算法和调优策略,旨在帮助开发者理解如何有效提升Java应用的性能。文章采用通俗易懂的语言,结合具体实例,使读者能够轻松掌握复杂的内存管理概念,并应用于实际开发中。