From 8bbeef48f5ce520f4ccb080bc04cd40f8429234c Mon Sep 17 00:00:00 2001 From: Sacha Coppey Date: Thu, 19 Feb 2026 10:50:05 +0100 Subject: [PATCH] Make SerializationSupport.constructorAccessors use DynamicHub id instead of Class Object as key --- .../com/oracle/svm/core/hub/DynamicHub.java | 2 +- .../serialize/SerializationRegistry.java | 34 --- .../serialize/SerializationSupport.java | 193 +++++++++++------- .../SharedLayerSnapshotCapnProtoSchema.capnp | 4 +- .../imagelayer/SVMImageLayerLoader.java | 18 +- .../imagelayer/SVMImageLayerSnapshotUtil.java | 4 +- .../imagelayer/SVMImageLayerWriter.java | 4 +- ...redLayerSnapshotCapnProtoSchemaHolder.java | 65 ++---- .../serialize/SerializationFeature.java | 21 +- 9 files changed, 173 insertions(+), 172 deletions(-) delete mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/serialize/SerializationRegistry.java diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java index 271c0f4c32ae..29ac3b4a8fec 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java @@ -2563,7 +2563,7 @@ public FieldAccessor newFieldAccessor(Field field0, boolean override) { @Substitute private Constructor generateConstructor(Class cl, Constructor constructorToCall) { - ConstructorAccessor acc = (ConstructorAccessor) SerializationSupport.getSerializationConstructorAccessor(cl, constructorToCall.getDeclaringClass()); + ConstructorAccessor acc = (ConstructorAccessor) SerializationSupport.getRuntimeSerializationConstructorAccessor(cl, constructorToCall.getDeclaringClass()); /* * Unlike other root constructors, this constructor is not copied for mutation but directly * mutated, as it is not cached. To cache this constructor, setAccessible call must be done diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/serialize/SerializationRegistry.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/serialize/SerializationRegistry.java deleted file mode 100644 index f8c3d22e8d25..000000000000 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/serialize/SerializationRegistry.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2020, 2020, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2020, 2020, Alibaba Group Holding Limited. 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.core.reflect.serialize; - -import com.oracle.svm.core.hub.DynamicHub; - -public interface SerializationRegistry { - boolean isRegisteredForSerialization0(DynamicHub dynamicHub); - - Object getSerializationConstructorAccessor0(Class declaringClass, Class targetConstructorClass); -} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/serialize/SerializationSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/serialize/SerializationSupport.java index d277fad5f158..971e5dcc67b1 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/serialize/SerializationSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/serialize/SerializationSupport.java @@ -27,9 +27,9 @@ import java.io.Serializable; import java.lang.invoke.SerializedLambda; -import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; -import java.util.Objects; +import java.util.function.Consumer; +import java.util.function.Function; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.MapCursor; @@ -44,20 +44,19 @@ import com.oracle.svm.core.heap.UnknownObjectField; import com.oracle.svm.core.hub.DynamicHub; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonSupport; -import com.oracle.svm.shared.singletons.MultiLayeredImageSingleton; import com.oracle.svm.core.metadata.MetadataTracer; import com.oracle.svm.core.reflect.SubstrateConstructorAccessor; +import com.oracle.svm.shared.singletons.MultiLayeredImageSingleton; import com.oracle.svm.shared.singletons.traits.BuiltinTraits.AllAccess; import com.oracle.svm.shared.singletons.traits.BuiltinTraits.NoLayeredCallbacks; import com.oracle.svm.shared.singletons.traits.SingletonLayeredInstallationKind.MultiLayer; import com.oracle.svm.shared.singletons.traits.SingletonTraits; -import com.oracle.svm.core.util.ImageHeapMap; import com.oracle.svm.shared.util.VMError; import jdk.graal.compiler.java.LambdaUtils; @SingletonTraits(access = AllAccess.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = MultiLayer.class) -public class SerializationSupport implements SerializationRegistry { +public class SerializationSupport { @Platforms(Platform.HOSTED_ONLY.class) public static SerializationSupport currentLayer() { @@ -108,61 +107,65 @@ private StubForAbstractClass() { } } - private Constructor stubConstructor; + private DynamicHub stubConstructorClass; + @Platforms(Platform.HOSTED_ONLY.class) // + private DynamicHub serializedLambdaClass; - public static final class SerializationLookupKey { - private final Class declaringClass; - private final Class targetConstructorClass; + public record HostedSerializationLookupKey(DynamicHubKey declaringClassId, DynamicHubKey targetConstructorClassId) { + } - private SerializationLookupKey(Class declaringClass, Class targetConstructorClass) { - assert declaringClass != null && targetConstructorClass != null; - this.declaringClass = declaringClass; - this.targetConstructorClass = targetConstructorClass; - } + public record SerializationLookupKey(int declaringClassId, int targetConstructorClassId) { + } - public Class getDeclaringClass() { - return declaringClass; - } + @Platforms(Platform.HOSTED_ONLY.class) // + private EconomicMap hostedConstructorAccessors; + @UnknownObjectField(fullyQualifiedTypes = "org.graalvm.collections.EconomicMapImpl", availability = AfterCompilation.class) // + private EconomicMap constructorAccessors; - public Class getTargetConstructorClass() { - return targetConstructorClass; - } + /** + * The constructor accessors need to be rescanned manually because the + * {@link SerializationSupport#constructorAccessors} map is only available after compilation. + */ + @Platforms(Platform.HOSTED_ONLY.class) // + private Consumer objectRescanner; - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - SerializationLookupKey that = (SerializationLookupKey) o; - return declaringClass.equals(that.declaringClass) && targetConstructorClass.equals(that.targetConstructorClass); - } + public SerializationSupport() { + hostedConstructorAccessors = EconomicMap.create(); + constructorAccessors = null; + } - @Override - public int hashCode() { - return Objects.hash(declaringClass, targetConstructorClass); - } + @Platforms(Platform.HOSTED_ONLY.class) + public void setStubConstructor(DynamicHub stubConstructorClass) { + VMError.guarantee(this.stubConstructorClass == null, "Cannot set stubConstructor again"); + this.stubConstructorClass = stubConstructorClass; } - private final EconomicMap constructorAccessors; + @Platforms(Platform.HOSTED_ONLY.class) + public void setSerializedLambdaClass(DynamicHub serializedLambdaClass) { + VMError.guarantee(this.serializedLambdaClass == null, "Cannot set serializedLambdaClass again"); + this.serializedLambdaClass = serializedLambdaClass; + } @Platforms(Platform.HOSTED_ONLY.class) - public SerializationSupport() { - constructorAccessors = ImageHeapMap.create("constructorAccessors"); + private DynamicHub getSerializedLambdaClass() { + return serializedLambdaClass; } - public void setStubConstructor(Constructor stubConstructor) { - VMError.guarantee(this.stubConstructor == null, "Cannot reset stubConstructor"); - this.stubConstructor = stubConstructor; + @Platforms(Platform.HOSTED_ONLY.class) + public void setObjectRescanner(Consumer objectRescanner) { + VMError.guarantee(this.objectRescanner == null, "Cannot set objectRescanner again"); + this.objectRescanner = objectRescanner; } @Platforms(Platform.HOSTED_ONLY.class) - public Object addConstructorAccessor(Class declaringClass, Class targetConstructorClass, Object constructorAccessor) { + public Object addConstructorAccessor(DynamicHub declaringClass, DynamicHub targetConstructorClass, Object constructorAccessor) { VMError.guarantee(constructorAccessor instanceof SubstrateConstructorAccessor, "Not a SubstrateConstructorAccessor: %s", constructorAccessor); - SerializationLookupKey key = new SerializationLookupKey(declaringClass, targetConstructorClass); - return constructorAccessors.putIfAbsent(key, constructorAccessor); + VMError.guarantee(!BuildPhaseProvider.isHostedUniverseBuilt(), "Called too early"); + HostedSerializationLookupKey key = new HostedSerializationLookupKey(new DynamicHubKey(declaringClass), new DynamicHubKey(targetConstructorClass)); + objectRescanner.accept(constructorAccessor); + synchronized (hostedConstructorAccessors) { + return hostedConstructorAccessors.putIfAbsent(key, constructorAccessor); + } } @Platforms(Platform.HOSTED_ONLY.class) @@ -178,7 +181,7 @@ public SerializationLookupKey getKeyFromConstructorAccessorClass(Class constr @Platforms(Platform.HOSTED_ONLY.class) public boolean isGeneratedSerializationClassLoader(ClassLoader classLoader) { - var constructorAccessorsCursor = constructorAccessors.getEntries(); + var constructorAccessorsCursor = hostedConstructorAccessors.getEntries(); while (constructorAccessorsCursor.advance()) { if (constructorAccessorsCursor.getValue().getClass().getClassLoader() == classLoader) { return true; @@ -189,11 +192,11 @@ public boolean isGeneratedSerializationClassLoader(ClassLoader classLoader) { @Platforms(Platform.HOSTED_ONLY.class) public String getClassLoaderSerializationLookupKey(ClassLoader classLoader) { - var constructorAccessorsCursor = constructorAccessors.getEntries(); + var constructorAccessorsCursor = hostedConstructorAccessors.getEntries(); while (constructorAccessorsCursor.advance()) { if (constructorAccessorsCursor.getValue().getClass().getClassLoader() == classLoader) { var key = constructorAccessorsCursor.getKey(); - return key.declaringClass.getName() + key.targetConstructorClass.getName(); + return key.declaringClassId + " " + key.targetConstructorClassId; } } throw VMError.shouldNotReachHere("No constructor accessor uses the class loader %s", classLoader); @@ -216,14 +219,17 @@ public int getTypeID() { } } + @Platforms(Platform.HOSTED_ONLY.class) // + private EconomicMap hostedClasses = EconomicMap.create(); @UnknownObjectField(fullyQualifiedTypes = "org.graalvm.collections.EconomicMapImpl", availability = AfterCompilation.class) // - private final EconomicMap classes = EconomicMap.create(); + private EconomicMap classes = null; private final EconomicMap lambdaCapturingClasses = EconomicMap.create(); @Platforms(Platform.HOSTED_ONLY.class) public void registerSerializationTargetClass(AccessCondition cnd, DynamicHub hub, boolean preserved) { - synchronized (classes) { - var previous = classes.putIfAbsent(BuildPhaseProvider.isHostedUniverseBuilt() ? hub.getTypeID() : new DynamicHubKey(hub), RuntimeDynamicAccessMetadata.createHosted(cnd, preserved)); + VMError.guarantee(!BuildPhaseProvider.isHostedUniverseBuilt()); + synchronized (hostedClasses) { + var previous = hostedClasses.putIfAbsent(new DynamicHubKey(hub), RuntimeDynamicAccessMetadata.createHosted(cnd, preserved)); if (previous != null) { previous.addCondition(cnd); if (!preserved) { @@ -234,16 +240,30 @@ public void registerSerializationTargetClass(AccessCondition cnd, DynamicHub hub } public void replaceHubKeyWithTypeID() { - EconomicMap newEntries = EconomicMap.create(); - var cursor = classes.getEntries(); + VMError.guarantee(classes == null && hostedClasses != null, "The maps should only be replaced once"); + VMError.guarantee(constructorAccessors == null && hostedConstructorAccessors != null, "The maps should only be replaced once"); + classes = EconomicMap.create(); + replaceHubKeyWithTypeID(hostedClasses, classes, SerializationSupport::getTypeID); + hostedClasses = null; + constructorAccessors = EconomicMap.create(); + replaceHubKeyWithTypeID(hostedConstructorAccessors, constructorAccessors, SerializationSupport::replaceSerializationLookupKey); + hostedConstructorAccessors = null; + } + + private static void replaceHubKeyWithTypeID(EconomicMap hostedMap, EconomicMap map, Function converter) { + var cursor = hostedMap.getEntries(); while (cursor.advance()) { - Object key = cursor.getKey(); - if (key instanceof DynamicHubKey hubKey) { - newEntries.put(hubKey.getTypeID(), cursor.getValue()); - cursor.remove(); - } + T key = cursor.getKey(); + map.put(converter.apply(key), cursor.getValue()); } - classes.putAll(newEntries); + } + + private static SerializationLookupKey replaceSerializationLookupKey(HostedSerializationLookupKey key) { + return new SerializationLookupKey(getTypeID(key.declaringClassId()), getTypeID(key.targetConstructorClassId())); + } + + private static int getTypeID(Object classId) { + return ((DynamicHubKey) classId).getTypeID(); } @Platforms(Platform.HOSTED_ONLY.class) @@ -261,28 +281,24 @@ public boolean isLambdaCapturingClassRegistered(String lambdaCapturingClass) { return lambdaCapturingClasses.containsKey(lambdaCapturingClass); } - public static Object getSerializationConstructorAccessor(Class serializationTargetClass, Class targetConstructorClass) { + public static Object getRuntimeSerializationConstructorAccessor(Class serializationTargetClass, Class targetConstructorClass) { + SubstrateUtil.guaranteeRuntimeOnly(); Class declaringClass = serializationTargetClass; if (LambdaUtils.isLambdaClass(declaringClass)) { declaringClass = SerializedLambda.class; } - if (SubstrateUtil.HOSTED) { - Object constructorAccessor = currentLayer().getSerializationConstructorAccessor0(declaringClass, targetConstructorClass); + if (MetadataTracer.enabled()) { + MetadataTracer.singleton().traceSerializationType(declaringClass); + } + for (var singleton : layeredSingletons()) { + DynamicHub declaringHub = SubstrateUtil.cast(declaringClass, DynamicHub.class); + DynamicHub targetConstructorHub = SubstrateUtil.cast(targetConstructorClass, DynamicHub.class); + Object constructorAccessor = singleton.getSerializationConstructorAccessor0(declaringHub, targetConstructorHub, declaringClass.getModifiers()); if (constructorAccessor != null) { return constructorAccessor; } - } else { - if (MetadataTracer.enabled()) { - MetadataTracer.singleton().traceSerializationType(declaringClass); - } - for (var singleton : layeredSingletons()) { - Object constructorAccessor = singleton.getSerializationConstructorAccessor0(declaringClass, targetConstructorClass); - if (constructorAccessor != null) { - return constructorAccessor; - } - } } String targetConstructorClassName = targetConstructorClass.getName(); @@ -291,15 +307,35 @@ public static Object getSerializationConstructorAccessor(Class serializationT return null; } - @Override - public Object getSerializationConstructorAccessor0(Class declaringClass, Class rawTargetConstructorClass) { - VMError.guarantee(stubConstructor != null, "Called too early, no stub constructor yet."); - Class targetConstructorClass = Modifier.isAbstract(declaringClass.getModifiers()) ? stubConstructor.getDeclaringClass() : rawTargetConstructorClass; - return constructorAccessors.get(new SerializationLookupKey(declaringClass, targetConstructorClass)); + @Platforms(Platform.HOSTED_ONLY.class) + public static Object getHostedSerializationConstructorAccessor(DynamicHub serializationTargetClass, DynamicHub targetConstructorClass) { + SerializationSupport serializationSupport = currentLayer(); + DynamicHub declaringClass = serializationTargetClass; + + if (LambdaUtils.isLambdaClass(declaringClass.getHostedJavaClass())) { + declaringClass = serializationSupport.getSerializedLambdaClass(); + } + + VMError.guarantee(BuildPhaseProvider.isHostedUniverseBuilt(), "Called too early, hosted universe was not built yet."); + Object constructorAccessor = serializationSupport.getSerializationConstructorAccessor0(declaringClass, targetConstructorClass, declaringClass.getModifiers()); + if (constructorAccessor != null) { + return constructorAccessor; + } + + String targetConstructorClassName = targetConstructorClass.getName(); + MissingSerializationRegistrationUtils.reportSerialization(declaringClass.getHostedJavaClass(), + "type '" + declaringClass.getTypeName() + "' with target constructor class '" + targetConstructorClassName + "'"); + return null; + } + + public Object getSerializationConstructorAccessor0(DynamicHub declaringHub, DynamicHub rawTargetConstructorHub, int modifiers) { + VMError.guarantee(stubConstructorClass != null, "Called too early, no stub constructor yet."); + DynamicHub targetConstructorHub = Modifier.isAbstract(modifiers) ? stubConstructorClass : rawTargetConstructorHub; + return constructorAccessors.get(new SerializationLookupKey(declaringHub.getTypeID(), targetConstructorHub.getTypeID())); } public static boolean isRegisteredForSerialization(DynamicHub hub) { - for (SerializationRegistry singleton : SerializationSupport.layeredSingletons()) { + for (SerializationSupport singleton : SerializationSupport.layeredSingletons()) { if (singleton.isRegisteredForSerialization0(hub)) { return true; } @@ -307,13 +343,14 @@ public static boolean isRegisteredForSerialization(DynamicHub hub) { return false; } - @Override public boolean isRegisteredForSerialization0(DynamicHub dynamicHub) { + SubstrateUtil.guaranteeRuntimeOnly(); var conditionSet = classes.get(dynamicHub.getTypeID()); return conditionSet != null && conditionSet.satisfied(); } public static boolean isPreservedForSerialization(DynamicHub dynamicHub) { + SubstrateUtil.guaranteeRuntimeOnly(); for (SerializationSupport singleton : SerializationSupport.layeredSingletons()) { var conditionSet = singleton.classes.get(dynamicHub.getTypeID()); if (conditionSet != null) { diff --git a/substratevm/src/com.oracle.svm.hosted/resources/SharedLayerSnapshotCapnProtoSchema.capnp b/substratevm/src/com.oracle.svm.hosted/resources/SharedLayerSnapshotCapnProtoSchema.capnp index 35cf6cf938f4..2f4f0ba4e075 100644 --- a/substratevm/src/com.oracle.svm.hosted/resources/SharedLayerSnapshotCapnProtoSchema.capnp +++ b/substratevm/src/com.oracle.svm.hosted/resources/SharedLayerSnapshotCapnProtoSchema.capnp @@ -55,8 +55,8 @@ struct PersistedAnalysisType { wrappedType :union { none @31 :Void; # default serializationGenerated :group { - rawDeclaringClass @32 :Text; - rawTargetConstructor @33 :Text; + rawDeclaringClassId @32 :TypeId; + rawTargetConstructorId @33 :TypeId; } lambda :group { capturingClass @34 :Text; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerLoader.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerLoader.java index 47fd37487260..70dafdbb134b 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerLoader.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerLoader.java @@ -92,7 +92,6 @@ import com.oracle.svm.core.meta.MethodRef; import com.oracle.svm.core.reflect.proxy.DynamicProxySupport; import com.oracle.svm.core.reflect.serialize.SerializationSupport; -import com.oracle.svm.shared.util.VMError; import com.oracle.svm.hosted.FeatureImpl; import com.oracle.svm.hosted.SVMHost; import com.oracle.svm.hosted.classinitialization.ClassInitializationSupport; @@ -128,6 +127,7 @@ import com.oracle.svm.shaded.org.capnproto.PrimitiveList; import com.oracle.svm.shaded.org.capnproto.StructList; import com.oracle.svm.shaded.org.capnproto.Text; +import com.oracle.svm.shared.util.VMError; import com.oracle.svm.util.AnnotationUtil; import com.oracle.svm.util.GuestAccess; import com.oracle.svm.util.JVMCIReflectionUtil; @@ -446,14 +446,18 @@ protected boolean delegateLoadType(PersistedAnalysisType.Reader typeData) { } if (wrappedType.isSerializationGenerated()) { SerializationGenerated.Reader sg = wrappedType.getSerializationGenerated(); - String rawDeclaringClassName = sg.getRawDeclaringClass().toString(); - String rawTargetConstructorClassName = sg.getRawTargetConstructor().toString(); - Class rawDeclaringClass = imageLayerBuildingSupport.lookupClass(false, rawDeclaringClassName); - Class rawTargetConstructorClass = imageLayerBuildingSupport.lookupClass(false, rawTargetConstructorClassName); + int rawDeclaringClassId = sg.getRawDeclaringClassId(); + int rawTargetConstructorClassId = sg.getRawTargetConstructorId(); + AnalysisType rawDeclaringType = getAnalysisTypeForBaseLayerId(rawDeclaringClassId); + AnalysisType rawTargetConstructorType = getAnalysisTypeForBaseLayerId(rawTargetConstructorClassId); + Class rawDeclaringClass = rawDeclaringType.getJavaClass(); + Class rawTargetConstructorClass = rawTargetConstructorType.getJavaClass(); Constructor rawTargetConstructor = ReflectionUtil.lookupConstructor(rawTargetConstructorClass); Constructor constructor = ReflectionFactory.getReflectionFactory().newConstructorForSerialization(rawDeclaringClass, rawTargetConstructor); - SerializationSupport.currentLayer().addConstructorAccessor(rawDeclaringClass, rawTargetConstructorClass, SerializationFeature.getConstructorAccessor(constructor)); - Class constructorAccessor = SerializationSupport.getSerializationConstructorAccessor(rawDeclaringClass, rawTargetConstructorClass).getClass(); + DynamicHub rawDeclaringHub = typeToHub(rawDeclaringType); + DynamicHub rawTargetConstructorHub = typeToHub(rawTargetConstructorType); + SerializationSupport.currentLayer().addConstructorAccessor(rawDeclaringHub, rawTargetConstructorHub, SerializationFeature.getConstructorAccessor(constructor)); + Class constructorAccessor = SerializationSupport.getHostedSerializationConstructorAccessor(rawDeclaringHub, rawTargetConstructorHub).getClass(); metaAccess.lookupJavaType(constructorAccessor); return true; } else if (wrappedType.isLambda()) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerSnapshotUtil.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerSnapshotUtil.java index 597c408f66d4..0488d942f7d1 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerSnapshotUtil.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerSnapshotUtil.java @@ -81,11 +81,11 @@ import com.oracle.svm.hosted.meta.HostedUniverse; import com.oracle.svm.hosted.thread.VMThreadLocalCollector; import com.oracle.svm.shared.util.ModuleSupport; +import com.oracle.svm.shared.util.ReflectionUtil; import com.oracle.svm.shared.util.VMError; import com.oracle.svm.util.GuestAccess; import com.oracle.svm.util.JVMCIReflectionUtil; import com.oracle.svm.util.OriginalMethodProvider; -import com.oracle.svm.shared.util.ReflectionUtil; import jdk.graal.compiler.api.replacements.SnippetReflectionProvider; import jdk.graal.compiler.debug.CounterKey; @@ -340,7 +340,7 @@ private static String getGeneratedSerializationName(AnalysisType type) { } private static String generatedSerializationClassName(SerializationSupport.SerializationLookupKey serializationLookupKey) { - return GENERATED_SERIALIZATION + ":" + serializationLookupKey.getDeclaringClass() + "," + serializationLookupKey.getTargetConstructorClass(); + return GENERATED_SERIALIZATION + ":" + serializationLookupKey.declaringClassId() + "," + serializationLookupKey.targetConstructorClassId(); } private static String addModuleName(String elementName, String moduleName) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerWriter.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerWriter.java index 7a65caec0515..555ffc4504f4 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerWriter.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerWriter.java @@ -535,8 +535,8 @@ protected void delegatePersistType(AnalysisType type, PersistedAnalysisType.Buil if (type.toJavaName(true).contains(GENERATED_SERIALIZATION)) { WrappedType.SerializationGenerated.Builder b = builder.getWrappedType().initSerializationGenerated(); var key = SerializationSupport.currentLayer().getKeyFromConstructorAccessorClass(type.getJavaClass()); - b.setRawDeclaringClass(key.getDeclaringClass().getName()); - b.setRawTargetConstructor(key.getTargetConstructorClass().getName()); + b.setRawDeclaringClassId(key.declaringClassId()); + b.setRawTargetConstructorId(key.targetConstructorClassId()); } else if (LambdaUtils.isLambdaType(type)) { WrappedType.Lambda.Builder b = builder.getWrappedType().initLambda(); b.setCapturingClass(LambdaUtils.capturingClass(type.toJavaName())); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SharedLayerSnapshotCapnProtoSchemaHolder.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SharedLayerSnapshotCapnProtoSchemaHolder.java index 18b3fe49f25a..29face1e15cd 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SharedLayerSnapshotCapnProtoSchemaHolder.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SharedLayerSnapshotCapnProtoSchemaHolder.java @@ -42,7 +42,7 @@ @SuppressWarnings("all") public final class SharedLayerSnapshotCapnProtoSchemaHolder { public static class PersistedAnalysisType { - public static final com.oracle.svm.shaded.org.capnproto.StructSize STRUCT_SIZE = new com.oracle.svm.shaded.org.capnproto.StructSize((short)4,(short)14); + public static final com.oracle.svm.shaded.org.capnproto.StructSize STRUCT_SIZE = new com.oracle.svm.shaded.org.capnproto.StructSize((short)5,(short)13); public static final class Factory extends com.oracle.svm.shaded.org.capnproto.StructFactory { public Factory() { } @@ -360,8 +360,9 @@ public final WrappedType.Builder getWrappedType() { } public final WrappedType.Builder initWrappedType() { _setShortField(7,(short)0); + _setIntField(7,0); + _setIntField(8,0); _clearPointerField(12); - _clearPointerField(13); return new PersistedAnalysisType.WrappedType.Builder(segment, data, pointers, dataSize, pointerCount); } @@ -550,7 +551,7 @@ public final boolean getIsRecord() { } public static class WrappedType { - public static final com.oracle.svm.shaded.org.capnproto.StructSize STRUCT_SIZE = new com.oracle.svm.shaded.org.capnproto.StructSize((short)4,(short)14); + public static final com.oracle.svm.shaded.org.capnproto.StructSize STRUCT_SIZE = new com.oracle.svm.shaded.org.capnproto.StructSize((short)5,(short)13); public static final class Factory extends com.oracle.svm.shaded.org.capnproto.StructFactory { public Factory() { } @@ -606,8 +607,8 @@ public final SerializationGenerated.Builder getSerializationGenerated() { } public final SerializationGenerated.Builder initSerializationGenerated() { _setShortField(7, (short)PersistedAnalysisType.WrappedType.Which.SERIALIZATION_GENERATED.ordinal()); - _clearPointerField(12); - _clearPointerField(13); + _setIntField(7,0); + _setIntField(8,0); return new PersistedAnalysisType.WrappedType.SerializationGenerated.Builder(segment, data, pointers, dataSize, pointerCount); } @@ -693,7 +694,7 @@ public enum Which { _NOT_IN_SCHEMA, } public static class SerializationGenerated { - public static final com.oracle.svm.shaded.org.capnproto.StructSize STRUCT_SIZE = new com.oracle.svm.shaded.org.capnproto.StructSize((short)4,(short)14); + public static final com.oracle.svm.shaded.org.capnproto.StructSize STRUCT_SIZE = new com.oracle.svm.shaded.org.capnproto.StructSize((short)5,(short)13); public static final class Factory extends com.oracle.svm.shaded.org.capnproto.StructFactory { public Factory() { } @@ -720,36 +721,20 @@ public static final class Builder extends com.oracle.svm.shaded.org.capnproto.St public final Reader asReader() { return new Reader(segment, data, pointers, dataSize, pointerCount, 0x7fffffff); } - public final boolean hasRawDeclaringClass() { - return !_pointerFieldIsNull(12); + public final int getRawDeclaringClassId() { + return _getIntField(7); } - public final com.oracle.svm.shaded.org.capnproto.Text.Builder getRawDeclaringClass() { - return _getPointerField(com.oracle.svm.shaded.org.capnproto.Text.factory, 12, null, 0, 0); - } - public final void setRawDeclaringClass(com.oracle.svm.shaded.org.capnproto.Text.Reader value) { - _setPointerField(com.oracle.svm.shaded.org.capnproto.Text.factory, 12, value); - } - public final void setRawDeclaringClass(String value) { - _setPointerField(com.oracle.svm.shaded.org.capnproto.Text.factory, 12, new com.oracle.svm.shaded.org.capnproto.Text.Reader(value)); - } - public final com.oracle.svm.shaded.org.capnproto.Text.Builder initRawDeclaringClass(int size) { - return _initPointerField(com.oracle.svm.shaded.org.capnproto.Text.factory, 12, size); + public final void setRawDeclaringClassId(int value) { + _setIntField(7, value); } - public final boolean hasRawTargetConstructor() { - return !_pointerFieldIsNull(13); - } - public final com.oracle.svm.shaded.org.capnproto.Text.Builder getRawTargetConstructor() { - return _getPointerField(com.oracle.svm.shaded.org.capnproto.Text.factory, 13, null, 0, 0); - } - public final void setRawTargetConstructor(com.oracle.svm.shaded.org.capnproto.Text.Reader value) { - _setPointerField(com.oracle.svm.shaded.org.capnproto.Text.factory, 13, value); - } - public final void setRawTargetConstructor(String value) { - _setPointerField(com.oracle.svm.shaded.org.capnproto.Text.factory, 13, new com.oracle.svm.shaded.org.capnproto.Text.Reader(value)); + + public final int getRawTargetConstructorId() { + return _getIntField(8); } - public final com.oracle.svm.shaded.org.capnproto.Text.Builder initRawTargetConstructor(int size) { - return _initPointerField(com.oracle.svm.shaded.org.capnproto.Text.factory, 13, size); + public final void setRawTargetConstructorId(int value) { + _setIntField(8, value); } + } public static final class Reader extends com.oracle.svm.shaded.org.capnproto.StructReader { @@ -757,18 +742,12 @@ public static final class Reader extends com.oracle.svm.shaded.org.capnproto.Str super(segment, data, pointers, dataSize, pointerCount, nestingLimit); } - public boolean hasRawDeclaringClass() { - return !_pointerFieldIsNull(12); - } - public com.oracle.svm.shaded.org.capnproto.Text.Reader getRawDeclaringClass() { - return _getPointerField(com.oracle.svm.shaded.org.capnproto.Text.factory, 12, null, 0, 0); + public final int getRawDeclaringClassId() { + return _getIntField(7); } - public boolean hasRawTargetConstructor() { - return !_pointerFieldIsNull(13); - } - public com.oracle.svm.shaded.org.capnproto.Text.Reader getRawTargetConstructor() { - return _getPointerField(com.oracle.svm.shaded.org.capnproto.Text.factory, 13, null, 0, 0); + public final int getRawTargetConstructorId() { + return _getIntField(8); } } @@ -777,7 +756,7 @@ public com.oracle.svm.shaded.org.capnproto.Text.Reader getRawTargetConstructor() public static class Lambda { - public static final com.oracle.svm.shaded.org.capnproto.StructSize STRUCT_SIZE = new com.oracle.svm.shaded.org.capnproto.StructSize((short)4,(short)14); + public static final com.oracle.svm.shaded.org.capnproto.StructSize STRUCT_SIZE = new com.oracle.svm.shaded.org.capnproto.StructSize((short)5,(short)13); public static final class Factory extends com.oracle.svm.shaded.org.capnproto.StructFactory { public Factory() { } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/serialize/SerializationFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/serialize/SerializationFeature.java index 123259d7ffd0..5031713e7b3c 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/serialize/SerializationFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/serialize/SerializationFeature.java @@ -60,6 +60,9 @@ import org.graalvm.nativeimage.impl.RuntimeReflectionSupport; import org.graalvm.nativeimage.impl.RuntimeSerializationSupport; +import com.oracle.graal.pointsto.ObjectScanner.OtherReason; +import com.oracle.graal.pointsto.meta.AnalysisMetaAccess; +import com.oracle.graal.pointsto.meta.AnalysisType; import com.oracle.svm.configure.ConfigurationFile; import com.oracle.svm.configure.ConfigurationParserOption; import com.oracle.svm.configure.SerializationConfigurationParser; @@ -72,11 +75,12 @@ import com.oracle.svm.core.reflect.serialize.SerializationSupport; import com.oracle.svm.core.reflect.target.ReflectionSubstitutionSupport; import com.oracle.svm.core.util.BasedOnJDKFile; -import com.oracle.svm.shared.util.VMError; import com.oracle.svm.hosted.ConditionalConfigurationRegistry; import com.oracle.svm.hosted.ConfigurationTypeResolver; import com.oracle.svm.hosted.FeatureImpl; +import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl; import com.oracle.svm.hosted.ImageClassLoader; +import com.oracle.svm.hosted.SVMHost; import com.oracle.svm.hosted.classinitialization.ClassInitializationSupport; import com.oracle.svm.hosted.config.ConfigurationParserUtils; import com.oracle.svm.hosted.lambda.LambdaParser; @@ -85,6 +89,7 @@ import com.oracle.svm.hosted.reflect.ReflectionFeature; import com.oracle.svm.hosted.reflect.proxy.DynamicProxyFeature; import com.oracle.svm.hosted.reflect.proxy.ProxyRegistry; +import com.oracle.svm.shared.util.VMError; import com.oracle.svm.util.GuestAccess; import com.oracle.svm.util.LogUtils; import com.oracle.svm.shared.util.ReflectionUtil; @@ -458,10 +463,16 @@ private void registerConstructorAccessor(AccessCondition cnd, Class serializa void beforeAnalysis(Feature.BeforeAnalysisAccess beforeAnalysisAccess) { setAnalysisAccess(beforeAnalysisAccess); + BeforeAnalysisAccessImpl accessImpl = (BeforeAnalysisAccessImpl) beforeAnalysisAccess; + serializationSupport.setObjectRescanner(object -> accessImpl.rescanObject(object, OtherReason.UNKNOWN)); + universe = accessImpl.getUniverse(); stubConstructor = newConstructorForSerialization(SerializationSupport.StubForAbstractClass.class, null); pendingConstructorRegistrations.forEach(Runnable::run); pendingConstructorRegistrations = null; - serializationSupport.setStubConstructor(stubConstructor); + AnalysisMetaAccess metaAccess = accessImpl.getMetaAccess(); + SVMHost hostVM = accessImpl.getHostVM(); + serializationSupport.setStubConstructor(hostVM.dynamicHub(metaAccess.lookupJavaType(stubConstructor.getDeclaringClass()))); + serializationSupport.setSerializedLambdaClass(hostVM.dynamicHub(metaAccess.lookupJavaType(DynamicHub.class))); } private static void registerQueriesForInheritableMethod(boolean preserved, Class clazz, String methodName, Class... args) { @@ -715,7 +726,11 @@ private Class addConstructorAccessor(Class serializationTargetClass, Class } Class targetConstructorClass = targetConstructor.getDeclaringClass(); - serializationSupport.addConstructorAccessor(serializationTargetClass, targetConstructorClass, getConstructorAccessor(targetConstructor)); + AnalysisMetaAccess analysisMetaAccess = universe.getBigbang().getMetaAccess(); + AnalysisType serializationTargetType = analysisMetaAccess.lookupJavaType(serializationTargetClass); + AnalysisType targetConstructorType = analysisMetaAccess.lookupJavaType(targetConstructorClass); + SVMHost hostVM = (SVMHost) universe.hostVM(); + serializationSupport.addConstructorAccessor(hostVM.dynamicHub(serializationTargetType), hostVM.dynamicHub(targetConstructorType), getConstructorAccessor(targetConstructor)); return targetConstructorClass; } }