Java 7在OSX上如何决定分配的堆内存最大值(-Xmx)

3

如果在OSX捆绑包上没有指定Java 7的堆内存最大值(-Xmx),那么它是如何决定的呢?我已经阅读了手册页面,但没有任何提示。似乎比Java 6默认分配更多,并且我想知道它是否随机器可用内存而变化,这对我非常有用,因为我的应用程序受内存限制,但我不能将默认值设置得太高,否则该应用程序将无法在低规格机器上运行。


System.out.println(Runtime.getRuntime().maxMemory()); - farmer1992
我知道如何获取值,但我不明白它是如何决定设置的值的。 - Paul Taylor
1个回答

3

默认堆大小来自OpenJDK源代码 hotspot/src/share/vm/runtime/arguments.cpp

从源代码中复制注释

  // If the maximum heap size has not been set with -Xmx,
  // then set it as fraction of the size of physical memory,
  // respecting the maximum and minimum sizes of the heap.

分数 = 4

  product(uintx, MaxRAMFraction, 4,                                         \
          "Maximum fraction (1/n) of real memory used for maximum heap "    \
          "size")                                                           \
                                                                            \
  product(uintx, DefaultMaxRAMFraction, 4,                                  \
          "Maximum fraction (1/n) of real memory used for maximum heap "    \
          "size; deprecated: to be renamed to MaxRAMFraction")              \

MX的完整代码

void Arguments::set_heap_size() {
  if (!FLAG_IS_DEFAULT(DefaultMaxRAMFraction)) {
    // Deprecated flag
    FLAG_SET_CMDLINE(uintx, MaxRAMFraction, DefaultMaxRAMFraction);
  }

  const julong phys_mem =
    FLAG_IS_DEFAULT(MaxRAM) ? MIN2(os::physical_memory(), (julong)MaxRAM)
                            : (julong)MaxRAM;

  // If the maximum heap size has not been set with -Xmx,
  // then set it as fraction of the size of physical memory,
  // respecting the maximum and minimum sizes of the heap.
  if (FLAG_IS_DEFAULT(MaxHeapSize)) {
    julong reasonable_max = phys_mem / MaxRAMFraction;

    if (phys_mem <= MaxHeapSize * MinRAMFraction) {
      // Small physical memory, so use a minimum fraction of it for the heap
      reasonable_max = phys_mem / MinRAMFraction;
    } else {
      // Not-small physical memory, so require a heap at least
      // as large as MaxHeapSize
      reasonable_max = MAX2(reasonable_max, (julong)MaxHeapSize);
    }
    if (!FLAG_IS_DEFAULT(ErgoHeapSizeLimit) && ErgoHeapSizeLimit != 0) {
      // Limit the heap size to ErgoHeapSizeLimit
      reasonable_max = MIN2(reasonable_max, (julong)ErgoHeapSizeLimit);
    }
    if (UseCompressedOops) {
      // Limit the heap size to the maximum possible when using compressed oops
      julong max_coop_heap = (julong)max_heap_for_compressed_oops();
      if (HeapBaseMinAddress + MaxHeapSize < max_coop_heap) {
        // Heap should be above HeapBaseMinAddress to get zero based compressed oops
        // but it should be not less than default MaxHeapSize.
        max_coop_heap -= HeapBaseMinAddress;
      }
      reasonable_max = MIN2(reasonable_max, max_coop_heap);
    }
    reasonable_max = os::allocatable_physical_memory(reasonable_max);

    if (!FLAG_IS_DEFAULT(InitialHeapSize)) {
      // An initial heap size was specified on the command line,
      // so be sure that the maximum size is consistent.  Done
      // after call to allocatable_physical_memory because that
      // method might reduce the allocation size.
      reasonable_max = MAX2(reasonable_max, (julong)InitialHeapSize);
    }

    if (PrintGCDetails && Verbose) {
      // Cannot use gclog_or_tty yet.
      tty->print_cr("  Maximum heap size " SIZE_FORMAT, reasonable_max);
    }
    FLAG_SET_ERGO(uintx, MaxHeapSize, (uintx)reasonable_max);
  }

  // If the initial_heap_size has not been set with InitialHeapSize
  // or -Xms, then set it as fraction of the size of physical memory,
  // respecting the maximum and minimum sizes of the heap.
  if (FLAG_IS_DEFAULT(InitialHeapSize)) {
    julong reasonable_minimum = (julong)(OldSize + NewSize);

    reasonable_minimum = MIN2(reasonable_minimum, (julong)MaxHeapSize);

    reasonable_minimum = os::allocatable_physical_memory(reasonable_minimum);

    julong reasonable_initial = phys_mem / InitialRAMFraction;

    reasonable_initial = MAX2(reasonable_initial, reasonable_minimum);
    reasonable_initial = MIN2(reasonable_initial, (julong)MaxHeapSize);

    reasonable_initial = os::allocatable_physical_memory(reasonable_initial);

    if (PrintGCDetails && Verbose) {
      // Cannot use gclog_or_tty yet.
      tty->print_cr("  Initial heap size " SIZE_FORMAT, (uintx)reasonable_initial);
      tty->print_cr("  Minimum heap size " SIZE_FORMAT, (uintx)reasonable_minimum);
    }
    FLAG_SET_ERGO(uintx, InitialHeapSize, (uintx)reasonable_initial);
    set_min_heap_size((uintx)reasonable_minimum);
  }
}

谢谢,这很有用,尽管了解它实际使用了多少物理内存会更好。此外,这是OpenJDK,Oracle版本是否实际执行相同的操作,并且现在Windows版本是否也适用。 - Paul Taylor
@PaulTaylor Oracle和OpenJDK之间的区别是什么?https://dev59.com/nmQm5IYBdhLWcg3wwxPF - farmer1992
基本上它使用了物理内存的四分之一,我想知道是否有一种方法可以设置比例? - Paul Taylor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接