MaxHeapSize in JVM

Summary

The JVM's MaxHeapSize option dictates the maximum heap memory, configurable using the -XX:MaxHeapSize VM argument. Developers can inspect the effective heap size via -XX:+PrintFlagsFinal or -XX:+PrintCommandLineFlags, though these flags might report different values. This observed discrepancy stems from the JVM's internal alignment and ergonomic adjustments. By default, the heap is 2MB aligned, a process detailed in the OpenJDK CollectorPolicy::compute_heap_alignment source, which rounds the specified size up to the nearest 2MB multiple for optimal performance.

MaxHeapSize is an option which is to set the JVM maximum heap size can be allocated. We can specify the MaxHeapSize as VM argument when we run the program by setting -XX:MaxHeapSize=, here can be 2M, 20M, 200M etc.

We can also view the current MaxHeapSize set by setting different JVM options. To view the MaxHeapSize, we can use two JVM options : -XX:+PrintFlagsFinal and -XX:+PrintCommandLineFlags. Below is one example when running -XX:+PrintFlagsFinal:

 bool MaxFDLimit                                = true            {product}
uintx MaxGCMinorPauseMillis                     = 4294967295      {product}
uintx MaxGCPauseMillis                          = 4294967295      {product}
uintx MaxHeapFreeRatio                          = 70              {product}
uintx MaxHeapSize                              := 1044381696      {product}
 intx MaxInlineLevel                            = 9               {product}
 intx MaxInlineSize                             = 35              {product}
 intx MaxJavaStackTraceDepth                    = 1024            {product}

If we run the command -XX:+PrintCommandLineFlags, we will see :

-XX:InitialHeapSize=65192896 -XX:MaxHeapSize=1043086336 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC

But have you noticed that the two MaxHeapSize is diferent, why?

The actual heap size may differ from what the user specified in the command line due to alignment and ergonomics adjustments. By default, the heap is 2MB aligned, you can check the source code from OpenJDK to see how this is implemented.

size_t CollectorPolicy::compute_heap_alignment() {
  // The card marking array and the offset arrays for old generations are
  // committed in os pages as well. Make sure they are entirely full (to
  // avoid partial page problems), e.g. if 512 bytes heap corresponds to 1
  // byte entry and the os page size is 4096, the maximum heap size should
  // be 512*4096 = 2MB aligned.

  // There is only the GenRemSet in Hotspot and only the GenRemSet::CardTable
  // is supported.
  // Requirements of any new remembered set implementations must be added here.
  size_t alignment = GenRemSet::max_alignment_constraint(GenRemSet::CardTable);

  // Parallel GC does its own alignment of the generations to avoid requiring a
  // large page (256M on some platforms) for the permanent generation.  The
  // other collectors should also be updated to do their own alignment and then
  // this use of lcm() should be removed.
  if (UseLargePages && !UseParallelGC) {
      // in presence of large pages we have to make sure that our
      // alignment is large page aware
      alignment = lcm(os::large_page_size(), alignment);
  }

  return alignment;
}

1044381696 from -XX:+PrintFlagsFinal is the final heap size after 2MB-alignment of 1043086336 from -XX:+PrintCommandLineFlags . Since 1043086336 is not 2M-aligned, i.e. X / (2*1024*1024) = 497.38 - fractional. The nearest multiple of 2M to it is 1044381696: X / (2*1024*1024) = 498

JVM MAXHEAPSIZE ALIGNMENT

  RELATED

  COMMENTS

0

No comment for this article.