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