Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8272364

Parallel GC adaptive size policy may shrink the heap below MinHeapSize

XMLWordPrintable

    • gc
    • b22

      [~rkennke] reports that the heap size can become lower than -Xms / MinHeapSize.

      https://mail.openjdk.java.net/pipermail/hotspot-gc-dev/2021-August/036307.html

      ---
      I have an example that shows the 'problem':

      http://cr.openjdk.java.net/~rkennke/Example.java

      Reproduce it using:

      java -Xms1g -Xmx4g -XX:+UseParallelOldGC -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=20 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -Xlog:gc*=info,gc=debug,gc+heap*=trace,gc+ergo*=trace:file=gc.log:time,uptimemillis,level,tags Example 300

      Check the heap log for heap size entries:

      grep "Pause Young" gc.log

      This yields the following:

      http://cr.openjdk.java.net/~rkennke/gc-heapsize.txt

      It shows that the heap is indeed shrinking well below -Xms, e.g. ~600MB instead of 1024MB here:

      GC(12) Pause Young (Allocation Failure) 559M->589M(592M) 4,797ms
      ---

      The test case:
      ---
      import java.util.*;

      public class Example {

          // private static int LOOP_COUNT = Integer.MAX_VALUE;
          private static int LOOP_COUNT = 100;

          private static int DEFAULT_LIST_SIZE = 300; // default value (300 = 300MB)

          public static void main(String... args) {
              Example example = new Example();

              int listSize = DEFAULT_LIST_SIZE;
              if (args.length > 0) {
                  listSize = Integer.parseInt(args[0]);
              }

              for (int i = 0; i < LOOP_COUNT; i++) {
                  example.test(listSize);
                  try {
                      // Thread.sleep(100L);
                      Thread.sleep(500L);
                      // Thread.sleep(1000L);
                  } catch (Exception ignore) {}
              }
          }

          // specify enough size to listSize (depending on your heap setting),
          // so the ArrayList can be promoted to old gen and can trigger full GC.
          private void test(int listSize) {
              List list = new ArrayList();
              for (int i = 0; i < listSize; i++) {
                  list.add(new byte[1024 * 1024]); // add 1MB byte array to ArrayList
              }
              // clear ArrayList at the end, so it can be GCed at full GC cycle
              list = new ArrayList();
          }
      }
      ---

      The heap size should stay within MinHeapSize and MaxHeapSize, so this seems to be a bug.

            zgu Zhengyu Gu
            stefank Stefan Karlsson
            Votes:
            0 Vote for this issue
            Watchers:
            10 Start watching this issue

              Created:
              Updated:
              Resolved: