From 0d81f9d6452641f1f16b92dd95d756ed86862d80 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Tue, 30 Sep 2025 10:32:19 +0200 Subject: [PATCH] Only call updateSizeParameters() if DynamicCollectionPolicy is used. --- .../oracle/svm/core/genscavenge/CollectionPolicy.java | 9 +++++++++ .../svm/core/genscavenge/DynamicCollectionPolicy.java | 10 ++++++++++ .../src/com/oracle/svm/core/genscavenge/GCImpl.java | 6 +----- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/CollectionPolicy.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/CollectionPolicy.java index c9f79bd8ea72..4f446021466c 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/CollectionPolicy.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/CollectionPolicy.java @@ -31,6 +31,7 @@ import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.Uninterruptible; import com.oracle.svm.core.heap.GCCause; +import com.oracle.svm.core.heap.OutOfMemoryUtil; import com.oracle.svm.core.heap.PhysicalMemory; import com.oracle.svm.core.util.UserError; import com.oracle.svm.util.ReflectionUtil; @@ -217,4 +218,12 @@ static boolean shouldCollectYoungGenSeparately(boolean defaultValue) { default boolean isOutOfMemory(UnsignedWord usedBytes) { return usedBytes.aboveThan(getMaximumHeapSize()); } + + /** + * Invoked after a garbage collection when the maximum heap size has been exceeded. Can be + * overridden to recover from OOM. + */ + default void onMaximumHeapSizeExceeded() { + throw OutOfMemoryUtil.heapSizeExceeded(); + } } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/DynamicCollectionPolicy.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/DynamicCollectionPolicy.java index 96ebd09d922f..b61c9418016f 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/DynamicCollectionPolicy.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/DynamicCollectionPolicy.java @@ -58,4 +58,14 @@ public boolean isOutOfMemory(UnsignedWord usedBytes) { return super.isOutOfMemory(usedBytes); } + + @Override + public void onMaximumHeapSizeExceeded() { + if (isOutOfMemory(HeapImpl.getAccounting().getUsedBytes())) { + super.onMaximumHeapSizeExceeded(); + } else { + /* No longer out-of-memory - update the heap size parameters to reflect that. */ + GCImpl.getPolicy().updateSizeParameters(); + } + } } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java index c44a2cbe986d..412cc94e02dd 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java @@ -190,11 +190,7 @@ private void collect(GCCause cause, boolean forceFullGC) { if (!hasNeverCollectPolicy()) { boolean outOfMemory = collectWithoutAllocating(cause, forceFullGC); if (outOfMemory) { - if (getPolicy().isOutOfMemory(HeapImpl.getAccounting().getUsedBytes())) { - throw OutOfMemoryUtil.heapSizeExceeded(); - } else { - GCImpl.getPolicy().updateSizeParameters(); - } + getPolicy().onMaximumHeapSizeExceeded(); } } }