Skip to content

Commit 2f0e65a

Browse files
committed
Introduce serializable flag to reflection metadata
1 parent c6b9200 commit 2f0e65a

File tree

14 files changed

+84
-25
lines changed

14 files changed

+84
-25
lines changed

docs/reference-manual/native-image/assets/reachability-metadata-schema-v1.0.0.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,11 @@
202202
"title": "Allow objects of this class to be instantiated with a call to jdk.internal.misc.Unsafe#allocateInstance or JNI's AllocObject",
203203
"type": "boolean",
204204
"default": false
205+
},
206+
"serializable": {
207+
"title": "Allow objects of this class to be serialized and deserialized",
208+
"type": "boolean",
209+
"default": false
205210
}
206211
},
207212
"additionalProperties": false

substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/config/ConfigurationType.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ static ConfigurationType copyAndMerge(ConfigurationType type, ConfigurationType
104104
private ConfigurationMemberAccessibility allPublicMethodsAccess = ConfigurationMemberAccessibility.NONE;
105105
private ConfigurationMemberAccessibility allDeclaredConstructorsAccess = ConfigurationMemberAccessibility.NONE;
106106
private ConfigurationMemberAccessibility allPublicConstructorsAccess = ConfigurationMemberAccessibility.NONE;
107+
private boolean serializable = false;
107108

108109
public ConfigurationType(UnresolvedConfigurationCondition condition, ConfigurationTypeDescriptor typeDescriptor, boolean includeAllElements) {
109110
this.condition = condition;
@@ -284,14 +285,15 @@ private void setFlagsFromOther(ConfigurationType other, BiPredicate<Boolean, Boo
284285
allPublicMethodsAccess = accessCombiner.apply(allPublicMethodsAccess, other.allPublicMethodsAccess);
285286
allDeclaredConstructorsAccess = accessCombiner.apply(allDeclaredConstructorsAccess, other.allDeclaredConstructorsAccess);
286287
allPublicConstructorsAccess = accessCombiner.apply(allPublicConstructorsAccess, other.allPublicConstructorsAccess);
288+
serializable = flagPredicate.test(serializable, other.serializable);
287289
}
288290

289291
private boolean isEmpty() {
290292
return methods == null && fields == null && allFlagsFalse();
291293
}
292294

293295
private boolean allFlagsFalse() {
294-
return !(allDeclaredClasses || allRecordComponents || allPermittedSubclasses || allNestMembers || allSigners || allPublicClasses ||
296+
return !(allDeclaredClasses || allRecordComponents || allPermittedSubclasses || allNestMembers || allSigners || allPublicClasses || serializable ||
295297
allDeclaredFieldsAccess != ConfigurationMemberAccessibility.NONE || allPublicFieldsAccess != ConfigurationMemberAccessibility.NONE ||
296298
allDeclaredMethodsAccess != ConfigurationMemberAccessibility.NONE || allPublicMethodsAccess != ConfigurationMemberAccessibility.NONE ||
297299
allDeclaredConstructorsAccess != ConfigurationMemberAccessibility.NONE || allPublicConstructorsAccess != ConfigurationMemberAccessibility.NONE);
@@ -451,6 +453,10 @@ public synchronized void setAllPublicConstructors(ConfigurationMemberAccessibili
451453
}
452454
}
453455

456+
public synchronized void setSerializable() {
457+
serializable = true;
458+
}
459+
454460
@Override
455461
public synchronized void printJson(JsonWriter writer) throws IOException {
456462
writer.appendObjectStart();
@@ -464,6 +470,7 @@ public synchronized void printJson(JsonWriter writer) throws IOException {
464470
printJsonBooleanIfSet(writer, allPublicMethodsAccess == ConfigurationMemberAccessibility.ACCESSED, "allPublicMethods");
465471
printJsonBooleanIfSet(writer, allDeclaredConstructorsAccess == ConfigurationMemberAccessibility.ACCESSED, "allDeclaredConstructors");
466472
printJsonBooleanIfSet(writer, allPublicConstructorsAccess == ConfigurationMemberAccessibility.ACCESSED, "allPublicConstructors");
473+
printJsonBooleanIfSet(writer, serializable, "serializable");
467474

468475
if (fields != null) {
469476
writer.appendSeparator().quote("fields").appendFieldSeparator();

substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/config/ParserConfigurationAdapter.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,12 @@ public void registerDeclaredConstructors(UnresolvedConfigurationCondition condit
167167
type.setAllDeclaredConstructors(queriedOnly ? ConfigurationMemberAccessibility.QUERIED : ConfigurationMemberAccessibility.ACCESSED);
168168
}
169169

170+
@Override
171+
public void registerAsSerializable(UnresolvedConfigurationCondition condition, ConfigurationType type) {
172+
VMError.guarantee(condition.isAlwaysTrue() || condition.equals(type.getCondition()), "condition is already a part of the type");
173+
type.setSerializable();
174+
}
175+
170176
@Override
171177
public String getTypeName(ConfigurationType type) {
172178
return type.getTypeDescriptor().toString();

substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/trace/SerializationProcessor.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434

3535
import com.oracle.svm.configure.config.ConfigurationSet;
3636
import com.oracle.svm.configure.config.SerializationConfiguration;
37+
import com.oracle.svm.configure.config.TypeConfiguration;
38+
import com.oracle.svm.core.configure.NamedConfigurationTypeDescriptor;
3739

3840
import jdk.graal.compiler.java.LambdaUtils;
3941

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

5962
if ("ObjectStreamClass.<init>".equals(function) || "ObjectInputStream.readClassDescriptor".equals(function)) {
6063
expectSize(args, 1);
@@ -68,7 +71,7 @@ void processEntry(EconomicMap<String, ?> entry, ConfigurationSet configurationSe
6871
if (className.contains(LambdaUtils.LAMBDA_CLASS_NAME_SUBSTRING)) {
6972
serializationConfiguration.registerLambdaCapturingClass(condition, className);
7073
} else {
71-
serializationConfiguration.register(condition, className);
74+
reflectionConfiguration.getOrCreateType(condition, new NamedConfigurationTypeDescriptor(className)).setSerializable();
7275
}
7376
} else if ("SerializedLambda.readResolve".equals(function)) {
7477
expectSize(args, 1);

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/LegacyReflectionConfigurationParser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ final class LegacyReflectionConfigurationParser<C, T> extends ReflectionConfigur
4242
"allDeclaredMethods", "allPublicMethods", "allDeclaredFields", "allPublicFields",
4343
"allDeclaredClasses", "allRecordComponents", "allPermittedSubclasses", "allNestMembers", "allSigners",
4444
"allPublicClasses", "methods", "queriedMethods", "fields", CONDITIONAL_KEY,
45-
"queryAllDeclaredConstructors", "queryAllPublicConstructors", "queryAllDeclaredMethods", "queryAllPublicMethods", "unsafeAllocated");
45+
"queryAllDeclaredConstructors", "queryAllPublicConstructors", "queryAllDeclaredMethods", "queryAllPublicMethods", "unsafeAllocated", "serializable");
4646

4747
private final boolean treatAllNameEntriesAsType;
4848

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ReflectionConfigurationParserDelegate.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ public interface ReflectionConfigurationParserDelegate<C, T> {
6868

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

71+
void registerAsSerializable(C condition, T clazz);
72+
7173
String getTypeName(T type);
7274

7375
String getSimpleName(T type);

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ReflectionMetadataParser.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
class ReflectionMetadataParser<C, T> extends ReflectionConfigurationParser<C, T> {
4040
private static final List<String> OPTIONAL_REFLECT_METADATA_ATTRS = Arrays.asList(CONDITIONAL_KEY,
4141
"allDeclaredConstructors", "allPublicConstructors", "allDeclaredMethods", "allPublicMethods", "allDeclaredFields", "allPublicFields",
42-
"methods", "fields", "unsafeAllocated");
42+
"methods", "fields", "unsafeAllocated", "serializable");
4343

4444
private final String combinedFileKey;
4545

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

116+
registerIfNotDefault(data, false, clazz, "serializable", () -> delegate.registerAsSerializable(condition, clazz));
117+
116118
MapCursor<String, Object> cursor = data.getEntries();
117119
while (cursor.advance()) {
118120
String name = cursor.getKey();

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/ConfigurationParserUtils.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,15 @@
5757
import com.oracle.svm.hosted.reflect.proxy.ProxyRegistry;
5858

5959
import jdk.graal.compiler.util.json.JsonParserException;
60+
import org.graalvm.nativeimage.impl.RuntimeSerializationSupport;
6061

6162
public final class ConfigurationParserUtils {
6263

6364
public static ReflectionConfigurationParser<ConfigurationCondition, Class<?>> create(String combinedFileKey, boolean strictMetadata,
64-
ConfigurationConditionResolver<ConfigurationCondition> conditionResolver, ReflectionRegistry registry, ProxyRegistry proxyRegistry, ImageClassLoader imageClassLoader) {
65+
ConfigurationConditionResolver<ConfigurationCondition> conditionResolver, ReflectionRegistry registry, ProxyRegistry proxyRegistry,
66+
RuntimeSerializationSupport<ConfigurationCondition> serializationSupport, ImageClassLoader imageClassLoader) {
6567
return ReflectionConfigurationParser.create(combinedFileKey, strictMetadata, conditionResolver,
66-
RegistryAdapter.create(registry, proxyRegistry, imageClassLoader),
68+
RegistryAdapter.create(registry, proxyRegistry, serializationSupport, imageClassLoader),
6769
ConfigurationFiles.Options.StrictConfiguration.getValue(),
6870
ConfigurationFiles.Options.WarnAboutMissingReflectionOrJNIMetadataElements.getValue(), TreatAllNameEntriesAsType.getValue());
6971
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/ReflectionRegistryAdapter.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,24 +27,28 @@
2727
import java.lang.reflect.Proxy;
2828
import java.util.Arrays;
2929

30-
import com.oracle.svm.hosted.reflect.ReflectionDataBuilder;
3130
import org.graalvm.nativeimage.impl.ConfigurationCondition;
3231
import org.graalvm.nativeimage.impl.RuntimeReflectionSupport;
32+
import org.graalvm.nativeimage.impl.RuntimeSerializationSupport;
3333

3434
import com.oracle.svm.core.TypeResult;
3535
import com.oracle.svm.core.configure.ConfigurationTypeDescriptor;
3636
import com.oracle.svm.core.configure.NamedConfigurationTypeDescriptor;
3737
import com.oracle.svm.hosted.ImageClassLoader;
38+
import com.oracle.svm.hosted.reflect.ReflectionDataBuilder;
3839
import com.oracle.svm.hosted.reflect.proxy.ProxyRegistry;
3940

4041
public class ReflectionRegistryAdapter extends RegistryAdapter {
4142
private final RuntimeReflectionSupport reflectionSupport;
4243
private final ProxyRegistry proxyRegistry;
44+
private final RuntimeSerializationSupport<ConfigurationCondition> serializationSupport;
4345

44-
ReflectionRegistryAdapter(RuntimeReflectionSupport reflectionSupport, ProxyRegistry proxyRegistry, ImageClassLoader classLoader) {
46+
ReflectionRegistryAdapter(RuntimeReflectionSupport reflectionSupport, ProxyRegistry proxyRegistry, RuntimeSerializationSupport<ConfigurationCondition> serializationSupport,
47+
ImageClassLoader classLoader) {
4548
super(reflectionSupport, classLoader);
4649
this.reflectionSupport = reflectionSupport;
4750
this.proxyRegistry = proxyRegistry;
51+
this.serializationSupport = serializationSupport;
4852
}
4953

5054
@Override
@@ -126,4 +130,9 @@ public void registerPublicConstructors(ConfigurationCondition condition, boolean
126130
public void registerDeclaredConstructors(ConfigurationCondition condition, boolean queriedOnly, Class<?> type) {
127131
reflectionSupport.registerAllDeclaredConstructorsQuery(condition, queriedOnly, type);
128132
}
133+
134+
@Override
135+
public void registerAsSerializable(ConfigurationCondition condition, Class<?> clazz) {
136+
serializationSupport.register(condition, clazz);
137+
}
129138
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/RegistryAdapter.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.graalvm.nativeimage.impl.ConfigurationCondition;
3636
import org.graalvm.nativeimage.impl.ReflectionRegistry;
3737
import org.graalvm.nativeimage.impl.RuntimeReflectionSupport;
38+
import org.graalvm.nativeimage.impl.RuntimeSerializationSupport;
3839

3940
import com.oracle.svm.core.TypeResult;
4041
import com.oracle.svm.core.configure.ConfigurationTypeDescriptor;
@@ -51,9 +52,10 @@ public class RegistryAdapter implements ReflectionConfigurationParserDelegate<Co
5152
private final ReflectionRegistry registry;
5253
private final ImageClassLoader classLoader;
5354

54-
public static RegistryAdapter create(ReflectionRegistry registry, ProxyRegistry proxyRegistry, ImageClassLoader classLoader) {
55+
public static RegistryAdapter create(ReflectionRegistry registry, ProxyRegistry proxyRegistry, RuntimeSerializationSupport<ConfigurationCondition> serializationSupport,
56+
ImageClassLoader classLoader) {
5557
if (registry instanceof RuntimeReflectionSupport) {
56-
return new ReflectionRegistryAdapter((RuntimeReflectionSupport) registry, proxyRegistry, classLoader);
58+
return new ReflectionRegistryAdapter((RuntimeReflectionSupport) registry, proxyRegistry, serializationSupport, classLoader);
5759
} else {
5860
return new RegistryAdapter(registry, classLoader);
5961
}
@@ -277,6 +279,10 @@ private void registerExecutable(ConfigurationCondition condition, boolean querie
277279
registry.register(condition, queriedOnly, executable);
278280
}
279281

282+
@Override
283+
public void registerAsSerializable(ConfigurationCondition condition, Class<?> clazz) {
284+
}
285+
280286
@Override
281287
public String getTypeName(Class<?> type) {
282288
return type.getTypeName();

0 commit comments

Comments
 (0)