---
title: 使能DynamicMaxHeap特性
description: "互联网客户目前普遍使用容器化部署应用的模式，容器场景下容器资源可垂直伸缩，当前OpenJDK的最大堆只能在启动时指定，无法动态扩缩，Java应用无法使用到容器扩容出的内存。"
url: https://www.hikunpeng.com/document/detail/zh/kunpengaccel/system-lib/ugbishengjdklib/kunpengaccel_jdk_06_0008.html
sourcePath: /source/zh/kunpengaccel/system-lib/ugbishengjdklib/kunpengaccel_jdk_06_0008.html
indexId: 34b8c9e5b5e09e610bcac94d9e1f9987f11518137534bd0a84fb8ea7679e5c0780
---
# 使能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扩展的最大堆目标值不能超过此值。默认情况下为96MB（与-XX:MaxHeapSize的默认值一致）。设置该值意味着要开启DynamicMaxHeap功能。该参数需配合-XX:MaxHeapSize（即-Xmx）一起使用，且大于-Xmx的值。目前仅支持G1GC下使用。该值超过32GB则禁用压缩指针，如果用户显式指定过压缩指针开启则弹出告警Max heap size too large for Compressed Oops并禁用压缩指针。不添加-XX:DynamicMaxHeapSizeLimit参数时默认特性不使能，不对原应用产生任何影响。
  - -XX:MaxHeapSize=<最大堆的初始值>
  - -XX:+UseG1GC：使能特性。
启动参数举例如下：
```
$JAVA_HOME/bin/java 
  -XX:+TraceDynamicMaxHeap \
  -XX:DynamicMaxHeapSizeLimit=4g \
  -XX:MaxHeapSize=1g \
  -XX:+UseG1GC \
```

开启特性的最少必需参数举例如下：
```
$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，还会打印更加详细的堆上限伸缩日志到应用的标准输出中。
