jvm 参数设置与分析

2022-06-27 12:29:23 浏览数 (1)

1. 概述

之前的文章中介绍了 jvm 内存管理和垃圾收集的相关内容,结合这些理论知识,通过合理设置参数才能将系统的性能得以提升。

2. JVM 主要参数

2.1. 基本的设置参数

JVM 设置参数的主要含义

参数名称

含义

默认值

说明

-Xms

最小堆大小

物理内存的 1/64(<1GB)

空闲堆内存小于40%(通过 MinHeapFreeRatio 参数可调整该阈值)时,jvm 会增大堆直到 -Xmx

-Xmx

最大堆大小

物理内存的 1/4(<1GB)

空闲堆内存大于70%(通过 MaxHeapFreeRatio 参数可以调整该阈值)时,jvm 会减小堆直到 -Xms

-Xmn

新生代大小

指 Eden 与两个 Survivor 空间之和,Sun 官方推荐配置为整个堆的 3/8

-XX:PermSize

方法区(永久代)大小

物理内存的 1/64

-

-Xss

每个线程的堆栈大小

1M

-

-XX:ThreadStackSize

线程堆栈大小

1M

主线程以 -Xss 设置为主,其他线程以该设置为主,一般采用默认值即可

-XX:NewRadio

新生代与老年代大小的比值

Xms=Xmx并且设置了Xmn的情况下,该参数不需要进行设置

-XX:SurvivorRatio

Eden 区域 Survivor 区大小的比值

-

-XX:LargePageSizeInBytes

内存页大小

128M

不可设置过大

-XX: UseFastAccessorMethods

是否使用原始类型的快速优化

-

-XX: DisableExplicitGC

是否关闭 System.gc()

-

-XX:MaxTenuringThreshold

垃圾最大年龄

N 次没有被回收的新生代资源自动放入老年代,只有使用串行GC时才有效

-XX:MaxGCPauseMillis

最大停顿时间

-

每次年轻代垃圾收集的最长时间

-Xnoclassgc

金庸垃圾回收

-

-XX:SoftRefLRUPolicyMSPerMB

没M堆内存中软引用存活时间

1s

-

-XX:PretenureSizeThreshold

对象超过多大自动在老年代分配

0

采用 Parallel Scavenge GC 时无效

-XX:TLABWasteTargetPercent

TLAB 占 eden 区的百分比

1%

-

-XX: CollectGen0First

FullGC时是否先YGC

false

-

2.2. 并行收集相关的参数

JVM 并行GC的设置参数

参数名称

含义

默认值

说明

-XX: UseParGC

使用 ParNew 收集器进行新生代收集

false

与 -XX: UseConcMarkSweepGC 相同

-XX:ParallelGCThreads

并行收集线程数

-

指定并行 GC 下的垃圾收集线程数,最好配置为与 CPU 数相等

-XX: UseParallelOldGC

设置老年代收集器为 Parallel Old

JDK1.6 起开始提供

-

-XX: UseAdaptiveSizePolicy

自动选择年轻代大小及 Survivor 比例

false

建议在使用并行收集器一直打开

-XX:GCTimeRatio

设置垃圾回收时间占用程序运行时间百分比

大于 0 小于 100,使用 Parallel Scavenge 时设置

-XX: UseAdaptiveSizePolicy

是否自动根据当前系统情况决定最大吞吐量的限制

false

使用 Parallel Scavenge 时设置

-XX: ScavengeBeforeFullGC

Full GC前调用YGC

true

-

2.3. CMS 相关参数

JVM CMS GC 的设置参数

参数名称

含义

默认值

说明

-XX: UseConcMarkSweepGC

启用 CMS GC

false

-

-XX:CMSFullGCsBeforeCompaction

运行多少次 GC 后进行一次内存压缩(碎片整理)

-

-

-XX: CMSParallelRemarkEnabled

降低标记停顿

false

-

-XX UseCMSCompactAtFullCollection

是否启用内存压缩(碎片整理)

-

建议开启

-XX: UseCMSInitiatingOccupancyOnly

手动触发 CMS

false

禁止 HotSpot 自动触发 CMS GC

-XX:CMSInitiatingOccupancyFraction

GC 触发阈值(百分比)

1.5为68,1.6为92

内存使用达到阈值则开始 GC,设置过大会有可能造成失败而进行 full GC

-XX: CMSIncrementalMode

设置为增量模式

false

运用于单CPU下,在 CMS 运行途中暂停,继续运行用户线程,下次增量 GC

-XX:CMSClassUnloadingEnabled

垃圾回收清理方法区时移除不再使用的 classes

-

-

-XX: CMSPermGenSweepingEnabled

是否清理方法区(永久代)

-

默认不清理

3. 设置规则

3.1. 年轻代大小选择

1. 响应时间优先的应用 — 尽可能增大年轻代大小,这也意味着老年代的大小会相对减少,因此同时要减少到达老年代的对象 2. 吞吐量优先应用 — 尽可能增大年轻代,可以选择并行垃圾收集,适合 8CPU 以上应用

无论如何,谨记不能将新生代设置过小,否则会造成新生代 GC 频繁,甚至让新生代对象直接进入老年代,从而触发 full GC。

3.2. 老年代大小选择

1. 响应时间优先的应用 — 通常老年代使用 CMS 进行并发收集,所以老年代不能设计过小,否则会因为内存过多造成频繁 full GC;如果设计过大,则需要较长的收集,因此需要结合并发收集信息、持久化并发收集次数、传统GC信息、年轻代和老年代的时间比例考虑具体的内存大小 2. 吞吐量优先应用 — 这样的应用通常需要大年轻代 小老年代,这样可以尽可能回收大部分短期对象,减少中期对象,而老年代存放长期存活对象

3.3. 老年代的内存碎片问题

如果使用 CMS 作为老年代收集器,那么由于他采取的标记清除算法,通常会造成碎片,如果最终空间不足,则会触发一次 full GC。 针对这种情况,需要进行如下配置: 1. -XX: UseCMSCompactAtFullCollection — 使用并发收集器时,开启对年老代的压缩 2. -XX:CMSFullGCsBeforeCompaction=0 — 上面配置开启的情况下,这里设置多少次Full GC后,对年老代进行压缩

3.4. 其他事项

1. linux 64 位操作系统中,jdk 消耗内存更多,执行速度更慢,但吞吐量更大 2. XMX 和 XMS 设置一样大,MaxPermSize 和 MinPermSize 设置一样大,这样可以减轻伸缩堆大小带来的压力 3. 使用CMS的好处是用尽量少的新生代,经验值是128M-256M, 然后老生代利用CMS并行收集, 这样能保证系统低延迟的吞吐效率。 实际上cms的收集停顿时间非常的短,2G的内存, 大约20-80ms的应用程序停顿时间 4. 系统停顿的时候可能是GC的问题也可能是程序的问题,多用jmap和jstack查看,或者killall -3 java,然后查看java控制台日志,能看出很多问题。 5. 如果用了缓存,那么年老代应该大一些 6. 采用并发回收时,年轻代小一点,年老代要大,因为年老大用的是并发回收,即使时间长点也不会影响其他程序继续运行,网站不会停顿

4. 问题分析 — promotion failed

产生 promotion failed 可能是两个原因引起的: 1. 新生代的 survivor 不足,年轻代中很多对象等待放入 survior 内存,致使 Survivor 空间不足,这些内存被放入老年代 2. 老年代没有足够的内存接纳来自年轻代的对象

解决这个问题,就要从这两个原因着手: 1. 增大 Survivor 区域大小,设置 -XX:SurvivorRatio=1 2. 降低 CMSInitiatingOccupancyFraction(如设置为 70),让老年代在较低阈值时被回收

可以推断出:eden from survivor < old gen区剩余内存时,不会出现promontion faild的情况,即: (Xmx-Xmn)(1-CMSInitiatingOccupancyFraction/100)>=(Xmn-Xmn/(SurvivorRatior 2)) 得到: CMSInitiatingOccupancyFraction <=((Xmx-Xmn)-(Xmn-Xmn/(SurvivorRatior 2)))/(Xmx-Xmn)100。

0 人点赞