-
Type:
Bug
-
Resolution: Unresolved
-
Priority:
P4
-
None
-
Affects Version/s: 21.0.9
-
Component/s: hotspot
-
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 ----------
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 ----------