使能DynamicMaxHeap特性
介绍
互联网客户目前普遍使用容器化部署应用的模式,容器场景下容器资源可垂直伸缩,当前OpenJDK的最大堆只能在启动时指定,无法动态扩缩,Java应用无法使用到容器扩容出的内存。
DynamicMaxHeap特性通过引入一个可被修改的动态最大堆概念,运行时通过jcmd命令修改最大堆的目标值来动态控制实际堆内存上限。使能DynamicMaxHeap特性,可允许用户在应用运行时动态更新Java堆内存的上限,而无需重启JVM。
场景建议
容器资源扩容后,需要动态扩展堆内存上限,以使应用可以使用到容器扩容出的资源,从而提升性能的场景。
使用约束
- 当毕昇JDK版本为8时支持DynamicMaxHeap特性,从毕昇JDK 8u452版本后开始支持。且应用需要使用G1垃圾回收器。
- 应用必须显式指定动态堆扩展的上限值-XX:DynamicMaxHeapSizeLimit和最大堆的初始值-XX:MaxHeapSize(即-Xmx),以明确堆扩展的上下限;同时要求DynamicMaxHeapSizeLimit > MaxHeapSize,以确保有堆向上扩展的空间。
- 应用不能显式设置-XX:OldSize/-XX:NewSize/-XX:MaxNewSize;使用本特性时必须保持-XX:UseAdaptiveGCBoundary为false(不显式设置时默认值即为false),-XX:UseAdaptiveSizePolicy为true(不显式设置时默认值即为true)。
- 本特性暂不支持和G1Uncommit共用,因此应用启动时不能设置-XX:+G1Uncommit(不显示设置时默认值即为false)。
- 开启本特性时,若应用启动时设置-XX: DynamicMaxHeapSizeLimit>32GB,则JVM将会禁用压缩指针。
使用方法
- 启动添加如下JVM参数使能DynamicMaxHeap特性。
- -XX:+TraceDynamicMaxHeap:bool,参数表示是否开启DynamicMaxHeap日志追踪功能。开启后,会记录堆上限扩展过程的日志和执行失败的具体原因,并输出到标准输出里,输出信息中包含ChangeMaxHeapOp关键字。
- -XX:DynamicMaxHeapSizeLimit=<堆扩展的上限值>:uintx,参数表示堆扩展的上限值,后续通过jcmd扩展的最大堆目标值不能超过此值。默认情况下为96M(与-XX:MaxHeapSize的默认值一致)。设置该值意味着要开启DynamicMaxHeap功能。该参数需配合-XX:MaxHeapSize(即-Xmx)一起使用,且大于-Xmx的值。目前仅支持G1GC下使用。该值超过32GB则禁用压缩指针,如果用户显式指定过压缩指针开启则弹出告警Max heap size too large for Compressed Oops并禁用压缩指针。不添加-XX:DynamicMaxHeapSizeLimit参数时默认特性不使能,不对原应用产生任何影响。
- -XX:MaxHeapSize=<最大堆的初始值>
- -XX:+UseG1GC:使能特性。
启动参数举例如下:
1 2 3 4 5
$JAVA_HOME/bin/java -XX:+TraceDynamicMaxHeap \ -XX:DynamicMaxHeapSizeLimit=4g \ -XX:MaxHeapSize=1g \ -XX:+UseG1GC \
开启特性的最少必需参数举例如下:
1$JAVA_HOME/bin/java -XX:DynamicMaxHeapSizeLimit=4g -XX:MaxHeapSize=1g -XX:+UseG1GC
- 在运行时可以通过下述jcmd命令调整最大堆目标值。
1$JAVA_HOME/bin/jcmd <PID> GC.change_max_heap <最大堆目标值>
本特性新增jcmd命令GC.change_max_heap用于调整最大堆的目标值。
- 使用方法:jcmd <PID> GC.change_max_heap <最大堆目标值>:该目标值数字只能是整数,可识别的单位字符为k/K(代表KB),m/M(代表MB),g/G(代表GB),不填或者填其他字符时默认数值是byte。
- 举例:
1 2
jcmd <PID> GC.change_max_heap 2g //合法,目标值为2GB jcmd <PID> GC.change_max_heap 209715200 //合法,目标值为200MB
- 当通过jcmd将JVM堆内存上限动态调低至当前堆使用量以下时,可能触发Young GC或Full GC(完全垃圾回收),从而引发应用性能波动。
调整成功时会返回GC.change_max_heap success;失败时则返回failed和失败原因。
若设置了-XX:+TraceDynamicMaxHeap,还会打印更加详细的堆上限伸缩日志到应用的标准输出中。