鲲鹏社区首页
中文
注册
开发者
我要评分
获取效率
正确性
完整性
易理解
在线提单
论坛求助

使能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将会禁用压缩指针。

使用方法

  1. 启动添加如下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
    
  2. 在运行时可以通过下述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,还会打印更加详细的堆上限伸缩日志到应用的标准输出中。