Skip to content

Commit

Permalink
Introduce serializable flag to reflection metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
loicottet committed Dec 3, 2024
1 parent c6b9200 commit 2bf72c6
Show file tree
Hide file tree
Showing 13 changed files with 77 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ static ConfigurationType copyAndMerge(ConfigurationType type, ConfigurationType
private ConfigurationMemberAccessibility allPublicMethodsAccess = ConfigurationMemberAccessibility.NONE;
private ConfigurationMemberAccessibility allDeclaredConstructorsAccess = ConfigurationMemberAccessibility.NONE;
private ConfigurationMemberAccessibility allPublicConstructorsAccess = ConfigurationMemberAccessibility.NONE;
private boolean serializable = false;

public ConfigurationType(UnresolvedConfigurationCondition condition, ConfigurationTypeDescriptor typeDescriptor, boolean includeAllElements) {
this.condition = condition;
Expand Down Expand Up @@ -284,14 +285,15 @@ private void setFlagsFromOther(ConfigurationType other, BiPredicate<Boolean, Boo
allPublicMethodsAccess = accessCombiner.apply(allPublicMethodsAccess, other.allPublicMethodsAccess);
allDeclaredConstructorsAccess = accessCombiner.apply(allDeclaredConstructorsAccess, other.allDeclaredConstructorsAccess);
allPublicConstructorsAccess = accessCombiner.apply(allPublicConstructorsAccess, other.allPublicConstructorsAccess);
serializable = flagPredicate.test(serializable, other.serializable);
}

private boolean isEmpty() {
return methods == null && fields == null && allFlagsFalse();
}

private boolean allFlagsFalse() {
return !(allDeclaredClasses || allRecordComponents || allPermittedSubclasses || allNestMembers || allSigners || allPublicClasses ||
return !(allDeclaredClasses || allRecordComponents || allPermittedSubclasses || allNestMembers || allSigners || allPublicClasses || serializable ||
allDeclaredFieldsAccess != ConfigurationMemberAccessibility.NONE || allPublicFieldsAccess != ConfigurationMemberAccessibility.NONE ||
allDeclaredMethodsAccess != ConfigurationMemberAccessibility.NONE || allPublicMethodsAccess != ConfigurationMemberAccessibility.NONE ||
allDeclaredConstructorsAccess != ConfigurationMemberAccessibility.NONE || allPublicConstructorsAccess != ConfigurationMemberAccessibility.NONE);
Expand Down Expand Up @@ -451,6 +453,10 @@ public synchronized void setAllPublicConstructors(ConfigurationMemberAccessibili
}
}

public synchronized void setSerializable() {
serializable = true;
}

@Override
public synchronized void printJson(JsonWriter writer) throws IOException {
writer.appendObjectStart();
Expand All @@ -464,6 +470,7 @@ public synchronized void printJson(JsonWriter writer) throws IOException {
printJsonBooleanIfSet(writer, allPublicMethodsAccess == ConfigurationMemberAccessibility.ACCESSED, "allPublicMethods");
printJsonBooleanIfSet(writer, allDeclaredConstructorsAccess == ConfigurationMemberAccessibility.ACCESSED, "allDeclaredConstructors");
printJsonBooleanIfSet(writer, allPublicConstructorsAccess == ConfigurationMemberAccessibility.ACCESSED, "allPublicConstructors");
printJsonBooleanIfSet(writer, serializable, "serializable");

if (fields != null) {
writer.appendSeparator().quote("fields").appendFieldSeparator();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,12 @@ public void registerDeclaredConstructors(UnresolvedConfigurationCondition condit
type.setAllDeclaredConstructors(queriedOnly ? ConfigurationMemberAccessibility.QUERIED : ConfigurationMemberAccessibility.ACCESSED);
}

@Override
public void registerAsSerializable(UnresolvedConfigurationCondition condition, ConfigurationType type) {
VMError.guarantee(condition.isAlwaysTrue() || condition.equals(type.getCondition()), "condition is already a part of the type");
type.setSerializable();
}

@Override
public String getTypeName(ConfigurationType type) {
return type.getTypeDescriptor().toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@

import java.util.List;

import com.oracle.svm.configure.config.TypeConfiguration;
import com.oracle.svm.core.configure.NamedConfigurationTypeDescriptor;
import org.graalvm.collections.EconomicMap;
import org.graalvm.nativeimage.impl.UnresolvedConfigurationCondition;

Expand All @@ -55,6 +57,7 @@ void processEntry(EconomicMap<String, ?> entry, ConfigurationSet configurationSe
String function = (String) entry.get("function");
List<?> args = (List<?>) entry.get("args");
SerializationConfiguration serializationConfiguration = configurationSet.getSerializationConfiguration();
TypeConfiguration reflectionConfiguration = configurationSet.getReflectionConfiguration();

if ("ObjectStreamClass.<init>".equals(function) || "ObjectInputStream.readClassDescriptor".equals(function)) {
expectSize(args, 1);
Expand All @@ -68,7 +71,7 @@ void processEntry(EconomicMap<String, ?> entry, ConfigurationSet configurationSe
if (className.contains(LambdaUtils.LAMBDA_CLASS_NAME_SUBSTRING)) {
serializationConfiguration.registerLambdaCapturingClass(condition, className);
} else {
serializationConfiguration.register(condition, className);
reflectionConfiguration.get(condition, new NamedConfigurationTypeDescriptor(className)).setSerializable();
}
} else if ("SerializedLambda.readResolve".equals(function)) {
expectSize(args, 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ final class LegacyReflectionConfigurationParser<C, T> extends ReflectionConfigur
"allDeclaredMethods", "allPublicMethods", "allDeclaredFields", "allPublicFields",
"allDeclaredClasses", "allRecordComponents", "allPermittedSubclasses", "allNestMembers", "allSigners",
"allPublicClasses", "methods", "queriedMethods", "fields", CONDITIONAL_KEY,
"queryAllDeclaredConstructors", "queryAllPublicConstructors", "queryAllDeclaredMethods", "queryAllPublicMethods", "unsafeAllocated");
"queryAllDeclaredConstructors", "queryAllPublicConstructors", "queryAllDeclaredMethods", "queryAllPublicMethods", "unsafeAllocated", "serializable");

private final boolean treatAllNameEntriesAsType;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ public interface ReflectionConfigurationParserDelegate<C, T> {

boolean registerAllConstructors(C condition, boolean queriedOnly, T type);

void registerAsSerializable(C condition, T clazz);

String getTypeName(T type);

String getSimpleName(T type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
class ReflectionMetadataParser<C, T> extends ReflectionConfigurationParser<C, T> {
private static final List<String> OPTIONAL_REFLECT_METADATA_ATTRS = Arrays.asList(CONDITIONAL_KEY,
"allDeclaredConstructors", "allPublicConstructors", "allDeclaredMethods", "allPublicMethods", "allDeclaredFields", "allPublicFields",
"methods", "fields", "unsafeAllocated");
"methods", "fields", "unsafeAllocated", "serializable");

private final String combinedFileKey;

Expand Down Expand Up @@ -113,6 +113,8 @@ protected void parseClass(EconomicMap<String, Object> data) {
registerIfNotDefault(data, false, clazz, "allDeclaredFields", () -> delegate.registerDeclaredFields(condition, false, clazz));
registerIfNotDefault(data, false, clazz, "allPublicFields", () -> delegate.registerPublicFields(condition, false, clazz));

registerIfNotDefault(data, false, clazz, "serializable", () -> delegate.registerAsSerializable(condition, clazz));

MapCursor<String, Object> cursor = data.getEntries();
while (cursor.advance()) {
String name = cursor.getKey();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,15 @@
import com.oracle.svm.hosted.reflect.proxy.ProxyRegistry;

import jdk.graal.compiler.util.json.JsonParserException;
import org.graalvm.nativeimage.impl.RuntimeSerializationSupport;

public final class ConfigurationParserUtils {

public static ReflectionConfigurationParser<ConfigurationCondition, Class<?>> create(String combinedFileKey, boolean strictMetadata,
ConfigurationConditionResolver<ConfigurationCondition> conditionResolver, ReflectionRegistry registry, ProxyRegistry proxyRegistry, ImageClassLoader imageClassLoader) {
ConfigurationConditionResolver<ConfigurationCondition> conditionResolver, ReflectionRegistry registry, ProxyRegistry proxyRegistry,
RuntimeSerializationSupport<ConfigurationCondition> serializationSupport, ImageClassLoader imageClassLoader) {
return ReflectionConfigurationParser.create(combinedFileKey, strictMetadata, conditionResolver,
RegistryAdapter.create(registry, proxyRegistry, imageClassLoader),
RegistryAdapter.create(registry, proxyRegistry, serializationSupport, imageClassLoader),
ConfigurationFiles.Options.StrictConfiguration.getValue(),
ConfigurationFiles.Options.WarnAboutMissingReflectionOrJNIMetadataElements.getValue(), TreatAllNameEntriesAsType.getValue());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,27 @@
import java.lang.reflect.Proxy;
import java.util.Arrays;

import com.oracle.svm.hosted.reflect.ReflectionDataBuilder;
import org.graalvm.nativeimage.impl.ConfigurationCondition;
import org.graalvm.nativeimage.impl.RuntimeReflectionSupport;
import org.graalvm.nativeimage.impl.RuntimeSerializationSupport;

import com.oracle.svm.core.TypeResult;
import com.oracle.svm.core.configure.ConfigurationTypeDescriptor;
import com.oracle.svm.core.configure.NamedConfigurationTypeDescriptor;
import com.oracle.svm.hosted.ImageClassLoader;
import com.oracle.svm.hosted.reflect.ReflectionDataBuilder;
import com.oracle.svm.hosted.reflect.proxy.ProxyRegistry;

public class ReflectionRegistryAdapter extends RegistryAdapter {
private final RuntimeReflectionSupport reflectionSupport;
private final ProxyRegistry proxyRegistry;
private final RuntimeSerializationSupport<ConfigurationCondition> serializationSupport;

ReflectionRegistryAdapter(RuntimeReflectionSupport reflectionSupport, ProxyRegistry proxyRegistry, ImageClassLoader classLoader) {
ReflectionRegistryAdapter(RuntimeReflectionSupport reflectionSupport, ProxyRegistry proxyRegistry, RuntimeSerializationSupport<ConfigurationCondition> serializationSupport, ImageClassLoader classLoader) {
super(reflectionSupport, classLoader);
this.reflectionSupport = reflectionSupport;
this.proxyRegistry = proxyRegistry;
this.serializationSupport = serializationSupport;
}

@Override
Expand Down Expand Up @@ -126,4 +129,9 @@ public void registerPublicConstructors(ConfigurationCondition condition, boolean
public void registerDeclaredConstructors(ConfigurationCondition condition, boolean queriedOnly, Class<?> type) {
reflectionSupport.registerAllDeclaredConstructorsQuery(condition, queriedOnly, type);
}

@Override
public void registerAsSerializable(ConfigurationCondition condition, Class<?> clazz) {
serializationSupport.register(condition, clazz);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.graalvm.nativeimage.impl.ConfigurationCondition;
import org.graalvm.nativeimage.impl.ReflectionRegistry;
import org.graalvm.nativeimage.impl.RuntimeReflectionSupport;
import org.graalvm.nativeimage.impl.RuntimeSerializationSupport;

import com.oracle.svm.core.TypeResult;
import com.oracle.svm.core.configure.ConfigurationTypeDescriptor;
Expand All @@ -51,9 +52,9 @@ public class RegistryAdapter implements ReflectionConfigurationParserDelegate<Co
private final ReflectionRegistry registry;
private final ImageClassLoader classLoader;

public static RegistryAdapter create(ReflectionRegistry registry, ProxyRegistry proxyRegistry, ImageClassLoader classLoader) {
public static RegistryAdapter create(ReflectionRegistry registry, ProxyRegistry proxyRegistry, RuntimeSerializationSupport<ConfigurationCondition> serializationSupport, ImageClassLoader classLoader) {
if (registry instanceof RuntimeReflectionSupport) {
return new ReflectionRegistryAdapter((RuntimeReflectionSupport) registry, proxyRegistry, classLoader);
return new ReflectionRegistryAdapter((RuntimeReflectionSupport) registry, proxyRegistry, serializationSupport, classLoader);
} else {
return new RegistryAdapter(registry, classLoader);
}
Expand Down Expand Up @@ -277,6 +278,10 @@ private void registerExecutable(ConfigurationCondition condition, boolean querie
registry.register(condition, queriedOnly, executable);
}

@Override
public void registerAsSerializable(ConfigurationCondition condition, Class<?> clazz) {
}

@Override
public String getTypeName(Class<?> type) {
return type.getTypeName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,10 @@ public void afterRegistration(AfterRegistrationAccess arg) {

ConfigurationConditionResolver<ConfigurationCondition> conditionResolver = new NativeImageConditionResolver(access.getImageClassLoader(),
ClassInitializationSupport.singleton());
ReflectionConfigurationParser<ConfigurationCondition, Class<?>> parser = ConfigurationParserUtils.create(JNI_KEY, true, conditionResolver, runtimeSupport, null, access.getImageClassLoader());
ReflectionConfigurationParser<ConfigurationCondition, Class<?>> parser = ConfigurationParserUtils.create(JNI_KEY, true, conditionResolver, runtimeSupport, null, null,
access.getImageClassLoader());
loadedConfigurations = ConfigurationParserUtils.parseAndRegisterConfigurationsFromCombinedFile(parser, access.getImageClassLoader(), "JNI");
ReflectionConfigurationParser<ConfigurationCondition, Class<?>> legacyParser = ConfigurationParserUtils.create(null, false, conditionResolver, runtimeSupport, null,
ReflectionConfigurationParser<ConfigurationCondition, Class<?>> legacyParser = ConfigurationParserUtils.create(null, false, conditionResolver, runtimeSupport, null, null,
access.getImageClassLoader());
loadedConfigurations += ConfigurationParserUtils.parseAndRegisterConfigurations(legacyParser, access.getImageClassLoader(), "JNI",
ConfigurationFiles.Options.JNIConfigurationFiles, ConfigurationFiles.Options.JNIConfigurationResources, ConfigurationFile.JNI.getFileName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import org.graalvm.nativeimage.impl.AnnotationExtractor;
import org.graalvm.nativeimage.impl.ConfigurationCondition;
import org.graalvm.nativeimage.impl.RuntimeReflectionSupport;
import org.graalvm.nativeimage.impl.RuntimeSerializationSupport;

import com.oracle.graal.pointsto.ObjectScanner;
import com.oracle.graal.pointsto.infrastructure.UniverseMetaAccess;
Expand Down Expand Up @@ -292,11 +293,12 @@ public void duringSetup(DuringSetupAccess a) {
var conditionResolver = new NativeImageConditionResolver(access.getImageClassLoader(), ClassInitializationSupport.singleton());
reflectionData.duringSetup(access.getMetaAccess(), aUniverse);
ProxyRegistry proxyRegistry = ImageSingletons.lookup(ProxyRegistry.class);
RuntimeSerializationSupport<ConfigurationCondition> serializationSupport = RuntimeSerializationSupport.singleton();
ReflectionConfigurationParser<ConfigurationCondition, Class<?>> parser = ConfigurationParserUtils.create(REFLECTION_KEY, true, conditionResolver, reflectionData, proxyRegistry,
access.getImageClassLoader());
serializationSupport, access.getImageClassLoader());
loadedConfigurations = ConfigurationParserUtils.parseAndRegisterConfigurationsFromCombinedFile(parser, access.getImageClassLoader(), "reflection");
ReflectionConfigurationParser<ConfigurationCondition, Class<?>> legacyParser = ConfigurationParserUtils.create(null, false, conditionResolver, reflectionData, proxyRegistry,
access.getImageClassLoader());
serializationSupport, access.getImageClassLoader());
loadedConfigurations += ConfigurationParserUtils.parseAndRegisterConfigurations(legacyParser, access.getImageClassLoader(), "reflection",
ConfigurationFiles.Options.ReflectionConfigurationFiles, ConfigurationFiles.Options.ReflectionConfigurationResources,
ConfigurationFile.REFLECTION.getFileName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import com.oracle.svm.core.jdk.proxy.DynamicProxyRegistry;
import com.oracle.svm.core.reflect.proxy.DynamicProxySupport;
import com.oracle.svm.hosted.FallbackFeature;
import com.oracle.svm.hosted.FeatureImpl;
import com.oracle.svm.hosted.FeatureImpl.DuringAnalysisAccessImpl;
import com.oracle.svm.hosted.FeatureImpl.DuringSetupAccessImpl;
import com.oracle.svm.hosted.ImageClassLoader;
Expand All @@ -50,18 +51,25 @@
public final class DynamicProxyFeature implements InternalFeature {
private int loadedConfigurations;
private Field proxyCacheField;
private ProxyRegistry proxyRegistry;

@Override
public void duringSetup(DuringSetupAccess a) {
DuringSetupAccessImpl access = (DuringSetupAccessImpl) a;

public void afterRegistration(AfterRegistrationAccess a) {
FeatureImpl.AfterRegistrationAccessImpl access = (FeatureImpl.AfterRegistrationAccessImpl) a;
ImageClassLoader imageClassLoader = access.getImageClassLoader();
ConfigurationConditionResolver<ConfigurationCondition> conditionResolver = new NativeImageConditionResolver(imageClassLoader, ClassInitializationSupport.singleton());
DynamicProxySupport dynamicProxySupport = new DynamicProxySupport();
ImageSingletons.add(DynamicProxyRegistry.class, dynamicProxySupport);
ImageSingletons.add(RuntimeProxyCreationSupport.class, dynamicProxySupport);
ProxyRegistry proxyRegistry = new ProxyRegistry(dynamicProxySupport, imageClassLoader);
proxyRegistry = new ProxyRegistry(dynamicProxySupport, imageClassLoader);
ImageSingletons.add(ProxyRegistry.class, proxyRegistry);
}

@Override
public void duringSetup(DuringSetupAccess a) {
DuringSetupAccessImpl access = (DuringSetupAccessImpl) a;
ImageClassLoader imageClassLoader = access.getImageClassLoader();
ConfigurationConditionResolver<ConfigurationCondition> conditionResolver = new NativeImageConditionResolver(imageClassLoader, ClassInitializationSupport.singleton());

ProxyConfigurationParser<ConfigurationCondition> parser = new ProxyConfigurationParser<>(conditionResolver, ConfigurationFiles.Options.StrictConfiguration.getValue(), proxyRegistry);
loadedConfigurations = ConfigurationParserUtils.parseAndRegisterConfigurations(parser, imageClassLoader, "dynamic proxy",
ConfigurationFiles.Options.DynamicProxyConfigurationFiles, ConfigurationFiles.Options.DynamicProxyConfigurationResources,
Expand Down
Loading

0 comments on commit 2bf72c6

Please sign in to comment.