常用jvm参数配置

jvm参数

系统级参数

#让jvm以server模式运行,一旦开启默认是64位运行环境
-server 
#以32位或64位运行
-d32 或 -d64 
-verbose:class 显示类加载的信息(查看加载的先后顺序)
-Dproperty=value 设置属性4值例如:-Dkey="value"
#允许使用实验性参数比如在jdk14中使用zgc
-XX:+UnlockExperimentalVMOptions
# 配置jvm crash 输出路径,一般分析jvm hang住的时候比较有用
-XX:ErrorFile=${LOGDIR}/hs_err_%p.log


# 开启oom生成堆栈信息
-XX:+HeapDumpOnOutOfMemoryError
#在fullgc 之前进行堆输出
-XX:+HeapDumpBeforeFullGC
#在fullgc 之后进行堆输出
-XX:+HeapDumpAfterFullGC
-XX:HeapDumpPath=/app/logs/应用名/%p.bin

#使用并行线程创建对象
-XX:+UseTLAB
# 设置TLAB的空间大小
-XX:TLABSize=size

# 禁止System.gc()如果后台跑批可以开启
-XX:+DisableExplicitGC
# 直接替换现有引导路径,一旦指定这个,默认的jvm的lib都不会加载了
-Xbootclasspath:path
# 以冒号分隔的目录或jar文件,在引导路径之前加载
-Xbootclasspath/a:path
# 以冒号分隔的目录或jar文件,在引导路径之后加载
-Xbootclasspath/p:path

# java堆最佳化设置
-XX:+AggressiveHeap

2 基本参数

# xms 和xmx大小设置一致,防止内存分配震荡
#堆空间初始大小,单位有m(mb),g(gb)等
-Xms2g
#最大堆,单位有m(mb),g(gb)等
-Xmx2g
#新生代大小,通常为xmx的1/3,如果生成过快,基本上不进入老年代,建议调大新生代(特别是并发量比较高的系统)
-Xmn768m 
# 元空间大小,初始和最大不要一样,如果一样,最后回收成本较大,只要没有动态生成类功能,建议小一些
-XX:MetaspaceSize=64m   达到会触发fullgc,虽然fullgc回收元空间的成本比较大
# 最大元空间
-XX:MaxMetaspaceSize=256m  
#栈大小(栈空间属于线程私有,栈设置的越大,最后容纳的线程就越少,不同平台默认栈大小不一样,linux/x64:1m )如果没有特别深的调用,一般256就够了,
-Xss256k 
# 进入老年代的阈值
-XX:PretenureSizeThresold
# 对象多少次晋升到老年代的参数,默认15次,有些垃圾回收器会自优化,并发量较大适当减小(只针对分代垃圾回收器有用)
-XX:MaxTenuringThreshold
# 关闭手动gc(系统里的System.gc())
-XX:+DisableExplicitGC


#缩小堆内存的时机,堆内存使用率大于70时扩张堆内存,xms=xmx时该参数无效,默认值70
-XX:MaxHeapFreeRatio=70
#扩张堆内存的时机,堆内存使用率小于40时缩减堆内存,xms=xmx时该参数无效,默认值40
-XX:MinHeapFreeRatio=40
# survivor区和Eden区大小比率,比如:S区和Eden区占新生代比率为1:6,两个S区2:6
-XX:SurvivorRatio=6 
#新生代和老年代的占比,表示新生代:老年代 = 1:4 即老年代占整个堆的4/5;默认值=2
-XX:NewRatio=4 

3.日志输出参数

#  显示每次垃圾事件的信息
-verbose:gc 
#jdk 8以及之前log配置
# 打印gc详细信息
-XX:+PrintGCDetails   

# 打印gc时间戳
-XX:+PrintGCTimeStamps 
-XX:+PrintGCDateStamps
#打印gc停顿时间
-XX:+PrintGCApplicationStoppedTime

# 打印出jvm堆内存每个区域的使用情况
-XX:+PrintHeapAtGC
# 打印引用暂停时间
-XX:-UseGCLogFileRotation
# 打印存活实例年龄信息
-XX:+PrintTenuringDistribution

# gc日志输出路径
-Xloggc:filename  
#固定路径生成
-Xloggc:/app/logs/应用名/gc/gc.log
#根据时间生成 
-Xloggc:/app/logs/应用名/gc/gc-%t.log 

# 滚动生成日志,日志文件达到一定的大小后,生成
#开启 或 关闭 
-XX:+UseGCLogFileRotation  -XX:-UseGCLogFileRotation

#滚动GC日志文件数,默认0,不滚动
-XX:NumberOfGCLogFiles=4   
#GC文件滚动大小,需配置UseGCLogFileRotation,设置为0表示仅通过jcmd命令触发
-XX:GCLogFileSize=10m 


#jdk9 以后gclog配置语法如下:
-Xlog[:[selector][:[output][:[decorators][:output-options]]]]
命令行中最关键的参数是选择器(selector),它由标签(tag)和日志级别(level)共同组成
日志级别分为:由低到高(越高输出的日志越少)
例如:
-Xlog:gc*:gc.log
-Xlog:safepoint,classhisto*=trace,age*,gc*=info:file=/app/userApi/logs/gc/gc-%t.log:time,tid,tags:filecount=20,filesize=100m

4.jdk9之前和jdk9之后展示示例

● 查看gc基本信息
○ jdk9 之前使用 -XX:+PrintGC
○ jdk9 之后使用-Xlog:gc
● 查看gc详细信息
○ jdk9 之前使用 -XX:+PrintGCDetails
○ jdk9 之后使用-Xlog:gc*
● 查看GC前后堆、方法区可用容量变化
○ jdk9 之前使用 -XX:+PrintHeapAtGC
○ jdk9 之后使用-Xlog:gc+heap = debug
● 查看GC过程中用户线程并发时间以及停顿时间
○ jdk9 之前使用 -XX:+PrintGCApplicationConcurrentTime 以及 -XX:+PrintGCApplicationStoppedTime
○ jdk9 之后使用-Xlog:safepoint
● 查看收集器Ergonomics机制
○ jdk9 之前使用 -XX:+PrintAdaptiveSizePolicy
○ jdk9 之后使用-Xlog:gc+ergo*=trace
● 查看熬过收集后剩余对象的年龄分布信息
○ jdk9 之前使用 -XX:+PrintTenuringDistribution
○ jdk9 之后使用-Xlog:gc+age=trace

5.gc策略配置

# 设置用于垃圾回收的线程数。通常情况下可以和 CPU 数量相等。但在 CPU 数量比较多的情况下,设置相对较小的数值也是合理的
-XX:ParallelGCThreads=4
# 新生代可容纳的最大对象,大于此值的对象直接会分配到老年代,设置为0则没有限制。
# 避免在Eden区和Survivor区发生大量的内存复制,该参数只对Serial和ParNew收集器有效,Parallel Scavenge并不认识该参数
-XX:PretenureSizeThreshold=1000000 
# 并发gc的线程数,默认根据cpu数量订
-XX:ConcGCThreads=4
#进入老年代最小的GC年龄,年轻代对象转换为老年代对象最小年龄值,默认值7,对象在坚持过一次Minor GC之后,年龄就加1,每个对象在坚持过一次Minor GC之后,年龄就增加1
-XX:InitialTenuringThreshol=7
#进入老年代最大的GC年龄,年轻代对象转换为老年代对象最大年龄值,默认值15
-XX:MaxTenuringThreshold=15 
image.png

6.parallel 收集器参数

#在新生代使用并行收集器。
-XX:+UseParNewGC
#老年代使用并行回收收集器
-XX:+UseParallelOldGC
#设置最大垃圾收集停顿时间。它的值是一个大于 0 的整数。收集器在工作时,会调整 Java 堆大小或者其他一些参数,尽可能地把停顿时间控制在 MaxGCPauseMills 以内
-XX:MaxGCPauseMills=200
# 设置吞吐量大小,它的值是一个 0-100 之间的整数。假设 GCTimeRatio 的值为 n,那么系统将花费不超过 1/(1+n) 的时间用于垃圾收集。
-XX:GCTimeRatio=5
# 打开自适应 GC 策略。在这种模式下,新生代的大小,eden 和 survivor 的比例、晋升老年代的对象年龄等参数会被自动调整,以达到在堆大小、吞吐量和停顿时间之间的平衡点。
-XX:+UseAdaptiveSizePolicy:

7.cms垃圾收集器

# 开启cms
-XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode
#新生代使用并行收集器,老年代使用 CMS+串行收集器。
-XX:+UseConcMarkSweepGC
#使用增量模式,比较适合单 CPU。
-XX:+CMSIncrementalMode
#设定 CMS 的线程数量
-XX:+ParallelCMSThreads=2
#设置 CMS 收集器在老年代空间被使用多少后触发,默认为 68%
-XX:+CMSInitiatingOccupancyFraction
#设定进行多少次 CMS 垃圾回收后,进行一次内存压缩(慎用,如果频繁fullgc会严重影响性能)
-XX:+UseFullGCsBeforeCompaction
#允许对类元数据进行回收
-XX:+CMSClassUnloadingEnabled
#启用并行重标记
-XX:+CMSParallelRemarkEndable
#当永久区占用率达到这一百分比后,启动 CMS 回收 (前提是-XX:+CMSClassUnloadingEnabled 激活了)
-XX:CMSInitatingPermOccupancyFraction
#表示只在到达阈值的时候,才进行 CMS 回收
-XX:UseCMSInitatingOccupancyOnly
# 以下两个参数会减少垃圾碎片,开启CMS的压缩
-XX:+UseCMSCompactAtFullCollection  
# 默认为0,指经过多少次CMS FullGC才进行压缩
-XX:CMSFullGCsBeforeCompaction=2  
# 让老年代占用率达到该值就进行CMS GC,以降低浮动垃圾占满老年代的问题
# 默认92% 可以降低这个值,
-XX:CMSInitiatingOccupancyFraction

8.G1垃圾回收器

8.1 G1特点

● 还是分代,不过分代都融入到了region,每个region都会根据实际情况调整功能
● 大对象不属于新生代也不属于老年代,这点和之前分代不同,G1 认为大于region的一半就为大对象
● G1的大多数行为都把Humongous Region作为老年代的一部分来进行看待
● 回收最有价值的(每个region都会有价值计算),回收时会把存活的复制到一个新的region中,单个region较小,根据停顿时间能控制回收影响

region的大小必须是2的倍数
region 最多2048个,堆/2048≈ region大小
#使用 G1 回收器
-XX:+UseG1GC
# 手动指定region大小
-XX:G1HeapRegionSize
# 手动指定新生代的占比,默认占堆的5%
-XX:G1NewSizePercent
# 手动指定新生代的最大占比,默认不超过60%,达到阈值就youngGc
-XX:G1MaxNewSizePercent
#设置老年代占整个堆的比例,默认是45%,老年代达到阈值就触发Mixed GC (年轻代和老年代都回收)
-XX:InitiatingHeapOccupancyPercent 
#设置最大垃圾收集停顿时间  g1的一大好处
-XX:+MaxGCPauseMills=200
#设置停顿间隔时间
-XX:+GCPauseIntervalMills

8.2三种垃圾回收模式:

● Minor Gcc 模式
○ Young Gc,Eden区满了以后,就会触发
● Mixed Gc 模式
○ 老年代占整个堆的InitiatingHeapOccupancyPercent(默认45%) 比例时,就会触发Mixed Gc
○ 回收所有的年轻代Region+部分老年代的Region
● full Gc 模式
○ 当Mixed Gc的回收速度赶不上对象的生成速度时触发
○ 一旦由Mixed Gc降级到full Gc,将使用Serial GC收集器进行回收

9. zgc垃圾回收器

# 看情况,jdk15以后zgc就正式发布了
-XX:+UnlockExperimentalVMOptions 
-XX:+UseZGC 
# ZGC的官网介绍上基准测试中的32和服务器,128G堆的情况下,配置的ConcGCThread是4,配置的ParallelGCThreads是20
# 并行回收垃圾的线程数(默认是12.5%,8核以下默认是1),调大后垃圾回收速度加快,但是抢占cpu资源,可能导致用户线程抢不到cpu资源
-XX:ConcGCThreads=2
# STW阶段使用线程数,默认是总核数的60%
-XX:ParallelGCThreads=6 
# ZGC发生的最小时间间隔,单位秒,并发量大的时候,可以把这个参数调小,主动回收垃圾
-XX:ZCollectionInterval=120 
# ZGC触发自适应算法的修正系数,默认2,数值越大,越早的触发ZGC
-XX:ZAllocationSpikeTolerance=5 
# 是否启用主动回收,默认开启,这里的配置表示关闭
-XX:+UnlockDiagnosticVMOptions -XX:-ZProactive 
# 设置GC日志中的内容、格式、位置以及每个日志的大小
-Xlog:safepoint,classhisto*=trace,age*,gc*=info:file=/app/userApi/logs/gc/gc-%t.log:time,tid,tags:filecount=20,filesize=100m 
# 默认是开启支持NUMA的,不过,如果JVM探测到系统绑定的是CPU子集,就会自动禁用NUMA
-XX:+UseNUMAZGC
# 通过这个参数显示是启用还是禁用了NUMA(前提是操作系统支持NUMA,linux内核2.5以后才支持)
-XX:+UseNUMA
# 默认情况下ZGC会把不再使用的内存归还给操作系统(如果Xms和Xmx配置一致,该参数无意义)
-XX:ZUncommit
# 表示延迟多少秒jvm归还占用的内存资源给操作系统
-XX:ZUncommitDelay

9.1 特点

● ZGC的Region具有动态性,动态创建和小会,以及动态的区域容量大小;Region的分类:
○ 小型Region(Small Region):容量固定2MB,用于存放<256kb的小对象
○ 中型Region(Medium Region):容量固定为32MB,用于存放>=256KB,但小于4MB的对象;
○ 大型Region(Large Region):容量不固定,可以动态变化,但必须是2MB的整数倍,用于放置>=4mb的大对象
● 采用染色指针技术实现并发整理算法:
○ 将标记信息记在引用对象的指针上;
○ 可以说zgc的可达性分析是遍历对象的“引用图”;
○ 在linux下64位指针的高18位不能用来寻址,zgc的染色体指针技术盯上了剩余46位的指针宽度,将其高4位提取出来存储四个标志信息(同时也压缩了zgc能够管理内存不能超过4TB~2的42次方)
○ 用来标志:对象的三色标记状态、是否进入了重分配集、是否执行过finalize()方法。
染色指针的优势:
○ Region的存活对象被移走,立即能够被释放和重用掉;
○ 减少在垃圾收集过程中的内存屏障的使用次数;zgc未使用任何的写屏障,只用了读屏障
○ 可扩展的存储结构,方便日后进一步提升性能;
● 支持Numa架构

9.2 编译相关参数

# 开启分层编译,JDK8之后默认开启
-XX:+TieredCompilation
# 编译线程数,设置数量后,JVM会自动分配线程数,C1:C2 = 1:2
-XX:+CICompilerCount=N
# :OSR编译的阈值
-XX:TierXBackEdgeThreshold
# 开启分层编译后各层调用的阈值
-XX:TierXMinInvocationThreshold
# 开启分层编译后的编译阈值
-XX:TierXCompileThreshold
# 即时编译缓存大小,一般情况下不用修改,除非系统内即时编译的内容比较多
-XX:ReservedCodeCacheSize=128m  -XX:InitialCodeCacheSize=128m 
# 输出编译、内联、codeCache信息到文件。可以使用JITwatch的工具来分析编译日志。JITwatch首页的Open Log选中日志文件,点击Start就可以开始分析日志
-XX:+UnlockDiagnosticVMOptions -XX:+PrintCompilation -XX:+PrintInlining -XX:+PrintCodeCache -XX:+PrintCodeCacheOnCompilation -XX:+TraceClassLoading -XX:+LogCompilation -XX:LogFile= filename

9.3 不常用参数

# 反射优化,反射调用多少次后将本地实现改为动态实现(动态生成字节码),
-Dsun.reflect.inflationThreshold=  
#打印被jvm隐藏了的栈信息
-XX:+ShowHiddenFrames  
#invokeExact 会调用一个特殊的适配器LambdaForm 将LambdaForm导出成class文件
-Djava.lang.invoke.MethodHandle.DUMP_CLASS_FILES=true 
# 自动装箱拆箱缓存
-XX:AutoBoxCacheMax
# Integer 缓存上限 默认 -128->127(特别是Integer使用特别频繁的时候)
-Djava.lang.Integer.IntegerCache.high=128 
#关闭反射调用的Inflation 机制,直接使用动态实现(取消委派实现)
-Dsun.reflect.noInflation=true 
#内存对齐选项
-XX:ObjectAlignmentInBytes 
# 查看类加载和卸载信息
-verbose:class  -XX:+TraceClass-Loading -XX:+TraceClassUnLoading

10 jvm 优化

通用优化:
# 一定要加,以server模式运行
-server 
# xms 和xmx大小设置一致,防止内存分配震荡
#堆空间初始大小,单位有m(mb),g(gb)等
-Xms2g
#最大堆,单位有m(mb),g(gb)等
-Xmx2g
# 开启指针压缩,在64位系统上,默认是开启的,压缩指针只支持32G的内存,超过32G就又切回了64位
UseCompressedOops
适配优化:
# GC停顿时间
MaxGCPauseMills
#新生代大小,根据系统情况,可以适当调整新生代大小
-Xmn768m 
# 元空间大小,初始和最大不要一样,如果一样,最后回收成本较大,只要没有动态生成类功能,建议小一些
-XX:MetaspaceSize=64m   达到会触发fullgc,虽然fullgc回收元空间的成本比较大
# 最大元空间
-XX:MaxMetaspaceSize=256m  
# 进入老年代的阈值
-XX:PretenureSizeThresold
# 对象多少次晋升到老年代的参数,默认15次,有些垃圾回收器会自优化,并发量较大适当减小
-XX:MaxTenuringThreshold
其他的根据不同的垃圾回收器动态调整即可。

11 如何优化代码?

  1. 最简单的是熟读阿里规约,这里有各种防坑策略;
  2. 减少new对象,特别是在循环的时候(对象的频繁创建和销毁也是不小的负担)
  3. 对象的作用域尽可能的小,尽快的销毁;a = null ,只是协助gc快速释放,并不会立马被释放,也是在下次young Gc的时候释放
  4. 大对象在内存中尽可能的不要来回序列化反序列化
  5. 尽可能减小对象的大小,将并行度提升上去
  6. 尽可能不要重复调用(特别是修改别人的代码

引用 1:https://www.cnblogs.com/zh94/p/13546311.html
引用 2:https://tech.meituan.com/2020/08/06/new-zgc-practice-in-meituan.html
原文出处:https://www.yuque.com/docs/share/75a8346b-76ff-4798-b2f6-e1ba6e3e3563?#

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,026评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,655评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,726评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,204评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,558评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,731评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,944评论 2 314
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,698评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,438评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,633评论 2 247
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,125评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,444评论 3 255
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,137评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,103评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,888评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,772评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,669评论 2 271

推荐阅读更多精彩内容