ShenandoahGC performance degradation/hang with OOME handling in recursive code

XMLWordPrintable

    • gc
    • x86_64
    • os_x

      ADDITIONAL SYSTEM INFORMATION :
      OS: macOS 26.1

      JDK Version Affected: OpenJDK Runtime Environment (build 21.0.9)

      JDK Version Working: OpenJDK Runtime Environment (build 25.0.1)

      GC Type Exhibiting Issue: ShenandoahGC (-XX:+UseShenandoahGC)

      A DESCRIPTION OF THE PROBLEM :
      When executing the attached test case (a modified version of dead11) with ShenandoahGC enabled (-XX:+UseShenandoahGC) on JDK 21.0.9, the program exhibits extreme performance degradation, failing to complete execution even after 30 minutes. The same test completes successfully within approximately 30-120 seconds when using other GCs (SerialGC, G1GC, ParallelGC, ZGC) on the same JDK version.

      Key Observations:

      GC-Specific: The issue is isolated to the ShenandoahGC implementation in JDK 21.

      JDK Version Discrepancy: The identical test case and ShenandoahGC configuration run to completion in under 100 seconds on JDK 25.0.1, suggesting a regression fix or significant optimization between these releases.
      Test Pattern: The test involves a combination of:

      Infinite recursion via main() calling itself.

      Allocation of multi-dimensional WeakReference arrays (WeakReference[16][128][32]).

      Intentional throwing and catching of OutOfMemoryError (OOME).

      Volatile field updates.

      This behavior strongly indicates a pathological interaction within ShenandoahGC's concurrent or degenerated collection phases under the stress of this specific allocation/exception pattern, which appears to have been resolved by JDK 25.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Compile the attached test.java file.

      Run with the following command on JDK 21.0.9:

      bash
      java -XX:+UseShenandoahGC -Xms4g -Xmx4g test

      Monitor the execution time.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The program should execute and terminate within a timeframe similar to other GCs (seconds to a few minutes)
      ACTUAL -
      The program does not terminate. It appears to hang or enter a state of severe performance degradation, consuming CPU but making no progress towards completion even after 30 minutes of runtime.

      ---------- BEGIN SOURCE ----------
      import java.io.PrintStream;
      import java.lang.ref.WeakReference;
      import java.util.Random;

      public class test {
          int SIZE = 30;
          private WeakReference[][][] field_1810 = new WeakReference[16][128][32];
          public static long TRAPCOUNT = 0L;
          protected static volatile ArrayIndexOutOfBoundsException[] field_1818;

          int f() {
              try {
              } catch (OutOfMemoryError var2) {
                  ++TRAPCOUNT;
              }

              int[] var3 = new int[this.SIZE];
              
              for (int i = 0; i < this.SIZE; i++) {
                  var3[i] = i;
              }

              new test();

              return var3[12];
          }

          int fopt() {
              try {
                  throw new OutOfMemoryError();
              } catch (OutOfMemoryError var3) {
                  ++TRAPCOUNT;
              }

              int[] var4 = new int[this.SIZE];
              var4[12] = 12;

              Random var1 = new Random(-3L);
              int var2 = var4.length;

              if (var2 > 0) {
                  int randomIndex = var1.nextInt(var2);
                  var4[randomIndex] = 1;
              }

              var4[12] = 12;
              return 12;
          }

          public static void main(String[] var0) {
              try {
              } catch (OutOfMemoryError var4) {
                  TRAPCOUNT++;
                  InheritableThreadLocal[] var5 =new InheritableThreadLocal[16];
              }

              test var6 = new test();
              PrintStream var1 = System.out;

              try {
                  String[] var8 = new String[16];
                  field_1818 = new ArrayIndexOutOfBoundsException[16];
                  main(var8);

                  if (var6 != null) {
                      throw new OutOfMemoryError();
                  }
              } catch (OutOfMemoryError var3) {
                  ++TRAPCOUNT;
              }

              var1.println("f()=" + var6.f() + "; fopt()=" + var6.fopt());

              if (var6.f() == var6.fopt()) {
                  PrintStream var9 = System.out;
                  var6.field_1810 = new WeakReference[16][128][32];
                  var9.println("Test ShenandoahGCTimeOut.dead11 Passed.");
              } else {
                  throw new Error("Test ShenandoahGCTimeOut.dead11 Failed: f()=" + var6.f() + " != fopt()=" + var6.fopt());
              }
          }
      }
      ---------- END SOURCE ----------

            Assignee:
            William Kemper
            Reporter:
            Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: