diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AddressRangeCommittedMemoryProvider.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AddressRangeCommittedMemoryProvider.java index 35d63d4bed6b..6db8a46a6fb9 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AddressRangeCommittedMemoryProvider.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AddressRangeCommittedMemoryProvider.java @@ -112,8 +112,6 @@ public class AddressRangeCommittedMemoryProvider extends ChunkBasedCommittedMemo "Consider increasing the address space size (see option -XX:ReservedAddressSpaceSize)."); private static final OutOfMemoryError UNALIGNED_OUT_OF_ADDRESS_SPACE = new OutOfMemoryError("Could not allocate an unaligned heap chunk because the heap address space is exhausted. " + "Consider increasing the address space size (see option -XX:ReservedAddressSpaceSize)."); - private static final OutOfMemoryError ALIGNED_COMMIT_FAILED = new OutOfMemoryError("Could not commit the memory for an aligned heap chunk, OS may be out of memory."); - private static final OutOfMemoryError UNALIGNED_COMMIT_FAILED = new OutOfMemoryError("Could not commit the memory for an unaligned heap chunk, OS may be out of memory."); /** * This mutex is used by the GC and the application. The application may hold this mutex only in @@ -347,7 +345,7 @@ protected OutOfMemoryError reportAlignedChunkAllocationFailed(int error) { if (error == OUT_OF_ADDRESS_SPACE) { throw OutOfMemoryUtil.reportOutOfMemoryError(ALIGNED_OUT_OF_ADDRESS_SPACE); } else if (error == COMMIT_FAILED) { - throw OutOfMemoryUtil.reportOutOfMemoryError(ALIGNED_COMMIT_FAILED); + throw OutOfMemoryUtil.reportOutOfMemoryError(ALIGNED_CHUNK_COMMIT_FAILED); } else { throw VMError.shouldNotReachHereAtRuntime(); } @@ -372,7 +370,7 @@ protected OutOfMemoryError reportUnalignedChunkAllocationFailed(int error) { if (error == OUT_OF_ADDRESS_SPACE) { throw OutOfMemoryUtil.reportOutOfMemoryError(UNALIGNED_OUT_OF_ADDRESS_SPACE); } else if (error == COMMIT_FAILED) { - throw OutOfMemoryUtil.reportOutOfMemoryError(UNALIGNED_COMMIT_FAILED); + throw OutOfMemoryUtil.reportOutOfMemoryError(UNALIGNED_CHUNK_COMMIT_FAILED); } else { throw VMError.shouldNotReachHereAtRuntime(); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateDiagnostics.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateDiagnostics.java index 2f912ff5f7e9..e0c843a21cd5 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateDiagnostics.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateDiagnostics.java @@ -41,6 +41,7 @@ import org.graalvm.nativeimage.c.struct.RawStructure; import org.graalvm.nativeimage.c.struct.SizeOf; import org.graalvm.nativeimage.c.type.CCharPointer; +import org.graalvm.nativeimage.impl.ImageSingletonsSupport; import org.graalvm.word.Pointer; import org.graalvm.word.PointerBase; import org.graalvm.word.UnsignedWord; @@ -175,7 +176,7 @@ public static void printObjectInfo(Log log, Object obj) { log.string(obj.getClass().getName()); if (obj instanceof String s) { - log.string(": ").string(s, 60); + log.string(": \"").string(s, 60).string("\""); } else { int layoutEncoding = DynamicHub.fromClass(obj.getClass()).getLayoutEncoding(); @@ -1306,12 +1307,14 @@ public static synchronized DiagnosticThunkRegistry singleton() { @Platforms(Platform.HOSTED_ONLY.class) public synchronized void add(DiagnosticThunk thunk) { + assert !BuildPhaseProvider.isAnalysisStarted(); thunks.add(thunk); resizeInitialInvocationCount(); } @Platforms(Platform.HOSTED_ONLY.class) public synchronized void add(int insertPos, DiagnosticThunk... extraThunks) { + assert !BuildPhaseProvider.isAnalysisStarted(); for (int i = 0; i < extraThunks.length; i++) { thunks.add(insertPos + i, extraThunks[i]); } @@ -1320,6 +1323,7 @@ public synchronized void add(int insertPos, DiagnosticThunk... extraThunks) { @Platforms(Platform.HOSTED_ONLY.class) public synchronized void addAfter(DiagnosticThunk thunk, Class before) { + assert !BuildPhaseProvider.isAnalysisStarted(); int insertPos = indexOf(before) + 1; assert insertPos > 0; thunks.add(insertPos, thunk); @@ -1370,13 +1374,13 @@ protected void onValueUpdate(EconomicMap, Object> values, Boolean o /* * Copy the value to a field in the image heap so that it is safe to access. During - * image build, it can happen that the singleton does not exist yet. In that case, - * the value will be copied to the image heap when executing the constructor of the - * singleton. This is a bit cumbersome but necessary because we can't use a static - * field. We also need to mark the option as used at run-time (see feature) as the - * static analysis would otherwise remove the option from the image. + * the image build, it can happen that the singleton does not exist yet. In that + * case, the value will be copied to the image heap when executing the constructor + * of the singleton. This is a bit cumbersome but necessary because we can't use a + * static field. We also need to mark the option as used at run-time (see feature) + * as the static analysis would otherwise remove the option from the image. */ - if (ImageSingletons.contains(Options.class)) { + if (wasConstructorExecuted()) { Options.singleton().loopOnFatalError = newValue; } } @@ -1389,7 +1393,7 @@ protected void onValueUpdate(EconomicMap, Object> values, Boolean o super.onValueUpdate(values, oldValue, newValue); /* See comment above. */ - if (ImageSingletons.contains(Options.class)) { + if (wasConstructorExecuted()) { Options.singleton().implicitExceptionWithoutStacktraceIsFatal = newValue; } } @@ -1417,6 +1421,10 @@ public static boolean shouldLoopOnFatalError() { public static boolean implicitExceptionWithoutStacktraceIsFatal() { return singleton().implicitExceptionWithoutStacktraceIsFatal; } + + private static boolean wasConstructorExecuted() { + return (!SubstrateUtil.HOSTED || ImageSingletonsSupport.isInstalled()) && ImageSingletons.contains(Options.class); + } } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java index bc50be77ed91..ecae60379efa 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java @@ -656,7 +656,7 @@ public static void updateMaxJavaStackTraceDepth(EconomicMap, Object } /* Same option name and specification as the Java HotSpot VM. */ - @Option(help = "Maximum total size of NIO direct-buffer allocations")// + @Option(help = "Maximum total size of NIO direct-buffer allocations", type = OptionType.Expert)// public static final RuntimeOptionKey MaxDirectMemorySize = new RuntimeOptionKey<>(0L); @Option(help = "Verify naming conventions during image construction.")// diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/OutOfMemoryUtil.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/OutOfMemoryUtil.java index 7536f4a2fed4..ef564b85f264 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/OutOfMemoryUtil.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/OutOfMemoryUtil.java @@ -33,6 +33,7 @@ import com.oracle.svm.core.jdk.JDKUtils; import com.oracle.svm.core.log.Log; import com.oracle.svm.core.stack.StackOverflowCheck; +import com.oracle.svm.core.thread.VMOperation; import com.oracle.svm.core.util.VMError; /** @@ -62,6 +63,11 @@ public static OutOfMemoryError reportOutOfMemoryError(OutOfMemoryError error) { @Uninterruptible(reason = "Not uninterruptible but it doesn't matter for the callers.", calleeMustBe = false) private static void reportOutOfMemoryError0(OutOfMemoryError error) { + if (VMOperation.isGCInProgress()) { + /* If a GC is in progress, then we can't execute the more complex logic below. */ + return; + } + if (VMInspectionOptions.hasHeapDumpSupport() && SubstrateOptions.HeapDumpOnOutOfMemoryError.getValue()) { HeapDumping.singleton().dumpHeapOnOutOfMemoryError(); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/ChunkBasedCommittedMemoryProvider.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/ChunkBasedCommittedMemoryProvider.java index 128f0c8775b7..f13272568908 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/ChunkBasedCommittedMemoryProvider.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/ChunkBasedCommittedMemoryProvider.java @@ -33,6 +33,7 @@ import com.oracle.svm.core.Uninterruptible; import com.oracle.svm.core.config.ConfigurationValues; +import com.oracle.svm.core.heap.OutOfMemoryUtil; import com.oracle.svm.core.heap.RestrictHeapAccess; import com.oracle.svm.core.nmt.NmtCategory; import com.oracle.svm.core.thread.VMOperation; @@ -41,9 +42,9 @@ import jdk.graal.compiler.word.Word; public abstract class ChunkBasedCommittedMemoryProvider extends AbstractCommittedMemoryProvider { - private static final OutOfMemoryError ALIGNED_OUT_OF_MEMORY_ERROR = new OutOfMemoryError("Could not allocate an aligned heap chunk. " + + protected static final OutOfMemoryError ALIGNED_CHUNK_COMMIT_FAILED = new OutOfMemoryError("Could not commit an aligned heap chunk. " + "Either the OS/container is out of memory or another system-level resource limit was reached (such as the number of memory mappings)."); - private static final OutOfMemoryError UNALIGNED_OUT_OF_MEMORY_ERROR = new OutOfMemoryError("Could not allocate an unaligned heap chunk. " + + protected static final OutOfMemoryError UNALIGNED_CHUNK_COMMIT_FAILED = new OutOfMemoryError("Could not commit an unaligned heap chunk. " + "Either the OS/container is out of memory or another system-level resource limit was reached (such as the number of memory mappings)."); @Fold @@ -56,7 +57,7 @@ public static ChunkBasedCommittedMemoryProvider get() { public Pointer allocateAlignedChunk(UnsignedWord nbytes, UnsignedWord alignment) { Pointer result = allocate(nbytes, alignment, false, NmtCategory.JavaHeap); if (result.isNull()) { - throw ALIGNED_OUT_OF_MEMORY_ERROR; + throw OutOfMemoryUtil.reportOutOfMemoryError(ALIGNED_CHUNK_COMMIT_FAILED); } return result; } @@ -66,7 +67,7 @@ public Pointer allocateAlignedChunk(UnsignedWord nbytes, UnsignedWord alignment) public Pointer allocateUnalignedChunk(UnsignedWord nbytes) { Pointer result = allocate(nbytes, getAlignmentForUnalignedChunks(), false, NmtCategory.JavaHeap); if (result.isNull()) { - throw UNALIGNED_OUT_OF_MEMORY_ERROR; + throw OutOfMemoryUtil.reportOutOfMemoryError(UNALIGNED_CHUNK_COMMIT_FAILED); } return result; }