Java的Xms和Xmx最小可以是多少

2023-03-15 13:40:21 浏览数 (3)

我们都知道在启动Java时,可以通过Xms和Xmx这两个参数来指定Java的最小堆内存和最大堆内存,但这两个参数的最小值又可以是多少呢?

下面我们通过OpenJDK源码看下。不过在此之前,我们先明确下OpenJDK的版本:

➜ jdk hg id 76072a077ee1 jdk-11 28

好了,进入源码部分。

首先,通过Xms和Xmx找到对应的参数解析代码(src/hotspot/share/runtime/arguments.cpp)

代码语言:javascript复制
} else if (match_option(option, "-Xms", &tail)) {
  julong long_initial_heap_size = 0;
  // an initial heap size of 0 means automatically determine
  ArgsRange errcode = parse_memory_size(tail, &long_initial_heap_size, 0);
  if (errcode != arg_in_range) {
    jio_fprintf(defaultStream::error_stream(),
                "Invalid initial heap size: %sn", option->optionString);
    describe_range_error(errcode);
    return JNI_EINVAL;
  }
  set_min_heap_size((size_t)long_initial_heap_size);
  // Currently the minimum size and the initial heap sizes are the same.
  // Can be overridden with -XX:InitialHeapSize.
  if (FLAG_SET_CMDLINE(size_t, InitialHeapSize, (size_t)long_initial_heap_size) != JVMFlag::SUCCESS) {
    return JNI_EINVAL;
  }
// -Xmx
} else if (match_option(option, "-Xmx", &tail) || match_option(option, "-XX:MaxHeapSize=", &tail)) {
  julong long_max_heap_size = 0;
  ArgsRange errcode = parse_memory_size(tail, &long_max_heap_size, 1);
  if (errcode != arg_in_range) {
    jio_fprintf(defaultStream::error_stream(),
                "Invalid maximum heap size: %sn", option->optionString);
    describe_range_error(errcode);
    return JNI_EINVAL;
  }
  if (FLAG_SET_CMDLINE(size_t, MaxHeapSize, (size_t)long_max_heap_size) != JVMFlag::SUCCESS) {
    return JNI_EINVAL;
  }
// Xmaxf
}

其中,第11行调用了set_min_heap_size方法,传入的是Xms的值 ,对应的代码为(src/hotspot/share/runtime/arguments.hpp)

代码语言:javascript复制
// -Xms
static size_t min_heap_size()             { return _min_heap_size; }
static void  set_min_heap_size(size_t v)  { _min_heap_size = v;  }

由上我们也可以看到,调用min_heap_size()方法返回的也是这个值。

第14行设置InitialHeapSize为Xms的值。

第27行设置MaxHeapSize为Xmx的值。

然后,我们再通过InitialHeapSize、MaxHeapSize找到代码(src/hotspot/share/gc/shared/collectorPolicy.cpp)

代码语言:javascript复制
void CollectorPolicy::initialize_flags() {
  assert(_space_alignment != 0, "Space alignment not set up properly");
  assert(_heap_alignment != 0, "Heap alignment not set up properly");
  assert(_heap_alignment >= _space_alignment,
         "heap_alignment: " SIZE_FORMAT " less than space_alignment: " SIZE_FORMAT,
         _heap_alignment, _space_alignment);
  assert(_heap_alignment % _space_alignment == 0,
         "heap_alignment: " SIZE_FORMAT " not aligned by space_alignment: " SIZE_FORMAT,
         _heap_alignment, _space_alignment);


  if (FLAG_IS_CMDLINE(MaxHeapSize)) {
    if (FLAG_IS_CMDLINE(InitialHeapSize) && InitialHeapSize > MaxHeapSize) {
      vm_exit_during_initialization("Initial heap size set to a larger value than the maximum heap size");
    }
    if (_min_heap_byte_size != 0 && MaxHeapSize < _min_heap_byte_size) {
      vm_exit_during_initialization("Incompatible minimum and maximum heap sizes specified");
    }
  }


  // Check heap parameter properties
  if (MaxHeapSize < 2 * M) {
    vm_exit_during_initialization("Too small maximum heap");
  }
  if (InitialHeapSize < M) {
    vm_exit_during_initialization("Too small initial heap");
  }
  if (_min_heap_byte_size < M) {
    vm_exit_during_initialization("Too small minimum heap");
  }

在上面的代码中我们发现,MaxHeapSize不能小于2M,InitialHeapSize不能小于1M。

上面还有个验证是_min_heap_byte_size不能小于1M,而_min_heap_byte_size值是来自(src/hotspot/share/gc/shared/collectorPolicy.cpp)

代码语言:javascript复制
CollectorPolicy::CollectorPolicy() :
    _space_alignment(0),
    _heap_alignment(0),
    _initial_heap_byte_size(InitialHeapSize),
    _max_heap_byte_size(MaxHeapSize),
    _min_heap_byte_size(Arguments::min_heap_size())
{}

Arguments::min_heap_size()方法,而这个方法也正是我们上面提到过的方法,返回的就是Xms的值。

综上可知,Xms最小要是1M,Xmx最小要是2M。

后来在 Java command 文档也发现有类似的说明,看来官方文档还是要好好看下的。

代码语言:javascript复制
-Xms size
This value must be a multiple of 1024 and greater than 1 MB.

-Xmx size
This value must be a multiple of 1024 and greater than 2 MB.

0 人点赞