From bf98664d56f4df06a174ea92b07464609b3e2341 Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Tue, 27 May 2025 22:10:21 +0200 Subject: [PATCH 1/2] Initialize sun management classes at run time. --- .../com/oracle/svm/core/jdk/management/ManagementFeature.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementFeature.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementFeature.java index c5e45d12f087..6aa08d6a510c 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementFeature.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementFeature.java @@ -100,6 +100,9 @@ public void duringSetup(DuringSetupAccess access) { RuntimeClassInitialization.initializeAtBuildTime("com.sun.jmx.mbeanserver.DefaultMXBeanMappingFactory$IdentityMapping"); RuntimeClassInitialization.initializeAtBuildTime("com.sun.jmx.mbeanserver.DescriptorCache"); RuntimeClassInitialization.initializeAtBuildTime("com.sun.jmx.remote.util.ClassLogger"); + + RuntimeClassInitialization.initializeAtRunTime("sun.management.MemoryImpl"); + RuntimeClassInitialization.initializeAtRunTime("com.sun.management.internal.PlatformMBeanProviderImpl"); } /** From 4610ea9bb98b77ec8553902bc61d483ac7d958ab Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Sun, 25 May 2025 18:43:23 +0200 Subject: [PATCH 2/2] Add support for catching missing arrays in hubs. --- .../hosted/image/NativeImageHeapWriter.java | 4 +- .../LayeredDispatchTableFeature.java | 11 +- .../imagelayer/LayeredDynamicHubFeature.java | 139 ++++++++++++++++++ .../hosted/imagelayer/LayeredImageHooks.java | 73 +++++++++ 4 files changed, 219 insertions(+), 8 deletions(-) create mode 100644 substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LayeredDynamicHubFeature.java create mode 100644 substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LayeredImageHooks.java diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageHeapWriter.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageHeapWriter.java index ec0b79effeb0..23398ec5499a 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageHeapWriter.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageHeapWriter.java @@ -64,7 +64,7 @@ import com.oracle.svm.hosted.config.HybridLayout; import com.oracle.svm.hosted.image.NativeImageHeap.ObjectInfo; import com.oracle.svm.hosted.imagelayer.CrossLayerConstantRegistryFeature; -import com.oracle.svm.hosted.imagelayer.LayeredDispatchTableFeature; +import com.oracle.svm.hosted.imagelayer.LayeredImageHooks; import com.oracle.svm.hosted.meta.HostedClass; import com.oracle.svm.hosted.meta.HostedField; import com.oracle.svm.hosted.meta.HostedInstanceClass; @@ -431,7 +431,7 @@ private void writeObject(ObjectInfo info, RelocatableBuffer buffer) { instanceFields = instanceFields.filter(field -> !dynamicHubLayout.isIgnoredField(field)); if (imageLayer) { - LayeredDispatchTableFeature.singleton().registerWrittenDynamicHub((DynamicHub) info.getObject(), heap.aUniverse, heap.hUniverse, vTable); + LayeredImageHooks.processWrittenDynamicHub(new LayeredImageHooks.WrittenDynamicHubInfo((DynamicHub) info.getObject(), heap.aUniverse, heap.hUniverse, vTable)); } } else if (heap.getHybridLayout(clazz) != null) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LayeredDispatchTableFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LayeredDispatchTableFeature.java index 7835ad49242e..88a927cb1edc 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LayeredDispatchTableFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LayeredDispatchTableFeature.java @@ -46,14 +46,12 @@ import com.oracle.graal.pointsto.infrastructure.OriginalMethodProvider; import com.oracle.graal.pointsto.meta.AnalysisMethod; import com.oracle.graal.pointsto.meta.AnalysisType; -import com.oracle.graal.pointsto.meta.AnalysisUniverse; import com.oracle.objectfile.ObjectFile; import com.oracle.svm.core.InvalidMethodPointerHandler; import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; import com.oracle.svm.core.feature.InternalFeature; import com.oracle.svm.core.graal.snippets.OpenTypeWorldDispatchTableSnippets; -import com.oracle.svm.core.hub.DynamicHub; import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; import com.oracle.svm.core.layeredimagesingleton.FeatureSingleton; import com.oracle.svm.core.meta.MethodPointer; @@ -67,7 +65,6 @@ import com.oracle.svm.hosted.meta.HostedMetaAccess; import com.oracle.svm.hosted.meta.HostedMethod; import com.oracle.svm.hosted.meta.HostedType; -import com.oracle.svm.hosted.meta.HostedUniverse; import com.oracle.svm.hosted.meta.VTableBuilder; import jdk.graal.compiler.code.CompilationResult; @@ -133,6 +130,7 @@ public void beforeAnalysis(Feature.BeforeAnalysisAccess access) { config.registerAsRoot(aMethod, false, "in prior layer dispatch table"); }); } + LayeredImageHooks.registerDynamicHubWrittenCallback(this::onDynamicHubWritten); } @Override @@ -395,12 +393,13 @@ private static void compareTypeInfo(HostedDispatchTable curInfo, PriorDispatchTa /* * Recording a hub was written to the heap */ - public void registerWrittenDynamicHub(DynamicHub hub, AnalysisUniverse aUniverse, HostedUniverse hUniverse, Object vTable) { - AnalysisType aType = ((SVMHost) aUniverse.hostVM()).lookupType(hub); - HostedType hType = hUniverse.lookup(aType); + public void onDynamicHubWritten(LayeredImageHooks.WrittenDynamicHubInfo hubInfo) { + AnalysisType aType = ((SVMHost) hubInfo.aUniverse().hostVM()).lookupType(hubInfo.hub()); + HostedType hType = hubInfo.hUniverse().lookup(aType); assert hType.getWrapped().isReachable() : "All installed hubs should be reachable " + hType; + Object vTable = hubInfo.vTable(); int vtableLength = Array.getLength(vTable); if (VTableBuilder.hasEmptyDispatchTable(hType)) { assert vtableLength == 0 : hType; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LayeredDynamicHubFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LayeredDynamicHubFeature.java new file mode 100644 index 000000000000..4169e4518621 --- /dev/null +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LayeredDynamicHubFeature.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.svm.hosted.imagelayer; + +import java.util.EnumSet; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.hosted.Feature; + +import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; +import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton; +import com.oracle.svm.core.feature.InternalFeature; +import com.oracle.svm.core.hub.DynamicHub; +import com.oracle.svm.core.imagelayer.BuildingInitialLayerPredicate; +import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; +import com.oracle.svm.core.layeredimagesingleton.FeatureSingleton; +import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader; +import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; +import com.oracle.svm.hosted.FeatureImpl; +import com.oracle.svm.hosted.meta.HostedType; +import com.oracle.svm.util.LogUtils; + +import jdk.graal.compiler.debug.Assertions; + +/** + * Tracks information about {@link DynamicHub} which should be consistent across builds. + */ +@AutomaticallyRegisteredFeature +public class LayeredDynamicHubFeature implements InternalFeature, FeatureSingleton { + + @Override + public boolean isInConfiguration(Feature.IsInConfigurationAccess access) { + return ImageLayerBuildingSupport.buildingImageLayer(); + } + + @Override + public void duringSetup(DuringSetupAccess access) { + if (ImageLayerBuildingSupport.buildingSharedLayer()) { + LayeredImageHooks.registerDynamicHubWrittenCallback(this::onDynamicHubWritten); + } + } + + void onDynamicHubWritten(LayeredImageHooks.WrittenDynamicHubInfo info) { + DynamicHub hub = info.hub(); + if (hub.getArrayHub() == null) { + DynamicHubMetadataTracking.singleton().recordMissingArrayHub(hub); + } + } + + @Override + public void beforeCompilation(BeforeCompilationAccess access) { + if (ImageLayerBuildingSupport.buildingApplicationLayer()) { + /* + * Scan all DynamicHubs to see if new missing array hubs have been installed. Currently + * we must wait to do this until after typeIDs have been assigned. + */ + DynamicHubMetadataTracking tracking = DynamicHubMetadataTracking.singleton(); + FeatureImpl.BeforeCompilationAccessImpl config = (FeatureImpl.BeforeCompilationAccessImpl) access; + config.getUniverse().getTypes().stream().filter(tracking::missingArrayHub).forEach(hType -> { + if (hType.getHub().getArrayHub() != null) { + var missingArrayName = hType.getHub().getArrayHub().getName(); + String message = String.format("New array type seen in application layer which was not installed within the dynamic hub.%nHub: %s%nArrayType: %s", hType.getHub().getName(), + missingArrayName); + LogUtils.warning(message); + } + }); + } + } +} + +@AutomaticallyRegisteredImageSingleton(onlyWith = BuildingInitialLayerPredicate.class) +class DynamicHubMetadataTracking implements LayeredImageSingleton { + private final Set typeIDsWithMissingHubs; + + DynamicHubMetadataTracking() { + this.typeIDsWithMissingHubs = ConcurrentHashMap.newKeySet(); + } + + DynamicHubMetadataTracking(Set missingHubSet) { + this.typeIDsWithMissingHubs = missingHubSet; + } + + static DynamicHubMetadataTracking singleton() { + return ImageSingletons.lookup(DynamicHubMetadataTracking.class); + } + + boolean missingArrayHub(HostedType hType) { + return typeIDsWithMissingHubs.contains(hType.getTypeID()); + } + + void recordMissingArrayHub(DynamicHub hub) { + var added = typeIDsWithMissingHubs.add(hub.getTypeID()); + assert added : Assertions.errorMessage("type recorded twice:", hub); + } + + @Override + public EnumSet getImageBuilderFlags() { + return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; + } + + @Override + public PersistFlags preparePersist(ImageSingletonWriter writer) { + writer.writeIntList("typeIDsWithMissingArrayHubs", typeIDsWithMissingHubs.stream().toList()); + return PersistFlags.CREATE; + } + + @SuppressWarnings("unused") + public static Object createFromLoader(ImageSingletonLoader loader) { + Set missingHubs = Set.copyOf(loader.readIntList("typeIDsWithMissingArrayHubs")); + + return new DynamicHubMetadataTracking(missingHubs); + } +} diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LayeredImageHooks.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LayeredImageHooks.java new file mode 100644 index 000000000000..86392929fd88 --- /dev/null +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LayeredImageHooks.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.svm.hosted.imagelayer; + +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Consumer; + +import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.hosted.Feature; + +import com.oracle.graal.pointsto.meta.AnalysisUniverse; +import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; +import com.oracle.svm.core.feature.InternalFeature; +import com.oracle.svm.core.hub.DynamicHub; +import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; +import com.oracle.svm.core.layeredimagesingleton.FeatureSingleton; +import com.oracle.svm.hosted.meta.HostedUniverse; + +/** + * Class containing hooks which can only be registered and executed during layered image builds. + */ +@AutomaticallyRegisteredFeature +public class LayeredImageHooks implements InternalFeature, FeatureSingleton { + private final Set> hubWrittenCallbacks = ConcurrentHashMap.newKeySet(); + + @Override + public boolean isInConfiguration(Feature.IsInConfigurationAccess access) { + return ImageLayerBuildingSupport.buildingImageLayer(); + } + + private static LayeredImageHooks singleton() { + return ImageSingletons.lookup(LayeredImageHooks.class); + } + + public record WrittenDynamicHubInfo(DynamicHub hub, AnalysisUniverse aUniverse, HostedUniverse hUniverse, Object vTable) { + + } + + /** + * Register a callback which will execute each time a new {@link DynamicHub} is installed in the + * image heap. + */ + public static void registerDynamicHubWrittenCallback(Consumer consumer) { + singleton().hubWrittenCallbacks.add(consumer); + } + + public static void processWrittenDynamicHub(WrittenDynamicHubInfo info) { + singleton().hubWrittenCallbacks.forEach(callback -> callback.accept(info)); + } +}