Skip to content

Commit ef2133d

Browse files
committed
Register reflectively-accessed types as JNI accessible
1 parent dea1968 commit ef2133d

File tree

6 files changed

+60
-21
lines changed

6 files changed

+60
-21
lines changed

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

+8-2
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,13 @@ final class LegacyReflectionConfigurationParser<C, T> extends ReflectionConfigur
4444
"queryAllDeclaredConstructors", "queryAllPublicConstructors", "queryAllDeclaredMethods", "queryAllPublicMethods", "unsafeAllocated");
4545

4646
private final boolean treatAllNameEntriesAsType;
47+
private final boolean typeOnly;
4748

4849
LegacyReflectionConfigurationParser(ConfigurationConditionResolver<C> conditionResolver, ReflectionConfigurationParserDelegate<C, T> delegate, boolean strictConfiguration,
49-
boolean printMissingElements, boolean treatAllNameEntriesAsType) {
50-
super(conditionResolver, delegate, strictConfiguration, printMissingElements);
50+
boolean printMissingElements, boolean treatAllNameEntriesAsType, boolean typeOnly) {
51+
super(conditionResolver, delegate, strictConfiguration, printMissingElements, "");
5152
this.treatAllNameEntriesAsType = treatAllNameEntriesAsType;
53+
this.typeOnly = typeOnly;
5254
}
5355

5456
@Override
@@ -93,6 +95,10 @@ protected void parseClass(EconomicMap<String, Object> data) {
9395
T clazz = result.get();
9496
delegate.registerType(conditionResult.get(), clazz);
9597

98+
if (typeOnly) {
99+
return;
100+
}
101+
96102
registerIfNotDefault(data, false, clazz, "allDeclaredConstructors", () -> delegate.registerDeclaredConstructors(condition, false, clazz));
97103
registerIfNotDefault(data, false, clazz, "allPublicConstructors", () -> delegate.registerPublicConstructors(condition, false, clazz));
98104
registerIfNotDefault(data, false, clazz, "allDeclaredMethods", () -> delegate.registerDeclaredMethods(condition, false, clazz));

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

+19-7
Original file line numberDiff line numberDiff line change
@@ -47,23 +47,31 @@ public abstract class ReflectionConfigurationParser<C, T> extends ConfigurationP
4747

4848
protected final ConfigurationConditionResolver<C> conditionResolver;
4949
protected final ReflectionConfigurationParserDelegate<C, T> delegate;
50+
protected final String combinedFileKey;
5051
private final boolean printMissingElements;
5152

5253
public ReflectionConfigurationParser(ConfigurationConditionResolver<C> conditionResolver, ReflectionConfigurationParserDelegate<C, T> delegate, boolean strictConfiguration,
53-
boolean printMissingElements) {
54+
boolean printMissingElements, String combinedFileKey) {
5455
super(strictConfiguration);
5556
this.conditionResolver = conditionResolver;
5657
this.printMissingElements = printMissingElements;
5758
this.delegate = delegate;
59+
this.combinedFileKey = combinedFileKey;
5860
}
5961

6062
public static <C, T> ReflectionConfigurationParser<C, T> create(String combinedFileKey, boolean strictMetadata,
6163
ConfigurationConditionResolver<C> conditionResolver, ReflectionConfigurationParserDelegate<C, T> delegate,
6264
boolean strictConfiguration, boolean printMissingElements, boolean treatAllEntriesAsType) {
65+
return create(combinedFileKey, strictMetadata, conditionResolver, delegate, strictConfiguration, printMissingElements, treatAllEntriesAsType, false);
66+
}
67+
68+
public static <C, T> ReflectionConfigurationParser<C, T> create(String combinedFileKey, boolean strictMetadata,
69+
ConfigurationConditionResolver<C> conditionResolver, ReflectionConfigurationParserDelegate<C, T> delegate,
70+
boolean strictConfiguration, boolean printMissingElements, boolean treatAllEntriesAsType, boolean typeOnly) {
6371
if (strictMetadata) {
64-
return new ReflectionMetadataParser<>(combinedFileKey, conditionResolver, delegate, strictConfiguration, printMissingElements);
72+
return new ReflectionMetadataParser<>(combinedFileKey, conditionResolver, delegate, strictConfiguration, printMissingElements, typeOnly);
6573
} else {
66-
return new LegacyReflectionConfigurationParser<>(conditionResolver, delegate, strictConfiguration, printMissingElements, treatAllEntriesAsType);
74+
return new LegacyReflectionConfigurationParser<>(conditionResolver, delegate, strictConfiguration, printMissingElements, treatAllEntriesAsType, typeOnly);
6775
}
6876
}
6977

@@ -76,8 +84,8 @@ protected void parseClassArray(List<Object> classes) {
7684
protected abstract void parseClass(EconomicMap<String, Object> data);
7785

7886
protected void registerIfNotDefault(EconomicMap<String, Object> data, boolean defaultValue, T clazz, String propertyName, Runnable register) {
79-
if (data.containsKey(propertyName)) {
80-
RuntimeReflectionSupport.increaseCount(false);
87+
if (data.containsKey(propertyName) && delegate.getClass().getName().contains("ReflectionRegistryAdapter")) {
88+
RuntimeReflectionSupport.increaseCount(combinedFileKey.equals(REFLECTION_KEY));
8189
}
8290
if (data.containsKey(propertyName) ? asBoolean(data.get(propertyName), propertyName) : defaultValue) {
8391
try {
@@ -96,7 +104,9 @@ protected void parseFields(C condition, List<Object> fields, T clazz) {
96104

97105
private void parseField(C condition, EconomicMap<String, Object> data, T clazz) {
98106
checkAttributes(data, "reflection field descriptor object", Collections.singleton("name"), Arrays.asList("allowWrite", "allowUnsafeAccess"));
99-
RuntimeReflectionSupport.increaseCount(false);
107+
if (delegate.getClass().getName().contains("ReflectionRegistryAdapter")) {
108+
RuntimeReflectionSupport.increaseCount(combinedFileKey.equals(REFLECTION_KEY));
109+
}
100110
String fieldName = asString(data.get("name"), "name");
101111
boolean allowWrite = data.containsKey("allowWrite") && asBoolean(data.get("allowWrite"), "allowWrite");
102112

@@ -117,7 +127,9 @@ protected void parseMethods(C condition, boolean queriedOnly, List<Object> metho
117127

118128
private void parseMethod(C condition, boolean queriedOnly, EconomicMap<String, Object> data, T clazz) {
119129
checkAttributes(data, "reflection method descriptor object", Collections.singleton("name"), Collections.singleton("parameterTypes"));
120-
RuntimeReflectionSupport.increaseCount(false);
130+
if (delegate.getClass().getName().contains("ReflectionRegistryAdapter")) {
131+
RuntimeReflectionSupport.increaseCount(combinedFileKey.equals(REFLECTION_KEY));
132+
}
121133
String methodName = asString(data.get("name"), "name");
122134
List<T> methodParameterTypes = null;
123135
Object parameterTypes = data.get("parameterTypes");

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

+11-5
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,12 @@ class ReflectionMetadataParser<C, T> extends ReflectionConfigurationParser<C, T>
4141
"allDeclaredConstructors", "allPublicConstructors", "allDeclaredMethods", "allPublicMethods", "allDeclaredFields", "allPublicFields",
4242
"methods", "fields", "unsafeAllocated");
4343

44-
private final String combinedFileKey;
44+
private boolean typeOnly;
4545

4646
ReflectionMetadataParser(String combinedFileKey, ConfigurationConditionResolver<C> conditionResolver, ReflectionConfigurationParserDelegate<C, T> delegate, boolean strictConfiguration,
47-
boolean printMissingElements) {
48-
super(conditionResolver, delegate, strictConfiguration, printMissingElements);
49-
this.combinedFileKey = combinedFileKey;
47+
boolean printMissingElements, boolean typeOnly) {
48+
super(conditionResolver, delegate, strictConfiguration, printMissingElements, combinedFileKey);
49+
this.typeOnly = typeOnly;
5050
}
5151

5252
@Override
@@ -60,7 +60,9 @@ public void parseAndRegister(Object json, URI origin) {
6060
@Override
6161
protected void parseClass(EconomicMap<String, Object> data) {
6262
checkAttributes(data, "reflection class descriptor object", List.of(TYPE_KEY), OPTIONAL_REFLECT_METADATA_ATTRS);
63-
RuntimeReflectionSupport.increaseCount(false);
63+
if (delegate.getClass().getName().contains("ReflectionRegistryAdapter")) {
64+
RuntimeReflectionSupport.increaseCount(combinedFileKey.equals(REFLECTION_KEY));
65+
}
6466

6567
Optional<ConfigurationTypeDescriptor> type = parseTypeContents(data.get(TYPE_KEY));
6668
if (type.isEmpty()) {
@@ -88,6 +90,10 @@ protected void parseClass(EconomicMap<String, Object> data) {
8890
T clazz = result.get();
8991
delegate.registerType(conditionResult.get(), clazz);
9092

93+
if (typeOnly) {
94+
return;
95+
}
96+
9197
delegate.registerDeclaredClasses(queryCondition, clazz);
9298
delegate.registerRecordComponents(queryCondition, clazz);
9399
delegate.registerPermittedSubclasses(queryCondition, clazz);

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,11 @@
6161
public final class ConfigurationParserUtils {
6262

6363
public static ReflectionConfigurationParser<ConfigurationCondition, Class<?>> create(String combinedFileKey, boolean strictMetadata,
64-
ConfigurationConditionResolver<ConfigurationCondition> conditionResolver, ReflectionRegistry registry, ProxyRegistry proxyRegistry, ImageClassLoader imageClassLoader) {
64+
ConfigurationConditionResolver<ConfigurationCondition> conditionResolver, ReflectionRegistry registry, ProxyRegistry proxyRegistry, ImageClassLoader imageClassLoader, boolean typeOnly) {
6565
return ReflectionConfigurationParser.create(combinedFileKey, strictMetadata, conditionResolver,
6666
RegistryAdapter.create(registry, proxyRegistry, imageClassLoader),
6767
ConfigurationFiles.Options.StrictConfiguration.getValue(),
68-
ConfigurationFiles.Options.WarnAboutMissingReflectionOrJNIMetadataElements.getValue(), TreatAllNameEntriesAsType.getValue());
68+
ConfigurationFiles.Options.WarnAboutMissingReflectionOrJNIMetadataElements.getValue(), TreatAllNameEntriesAsType.getValue(), typeOnly);
6969
}
7070

7171
/**

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNIAccessFeature.java

+9-3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
package com.oracle.svm.hosted.jni;
2626

2727
import static com.oracle.svm.core.configure.ConfigurationParser.JNI_KEY;
28+
import static com.oracle.svm.core.configure.ConfigurationParser.REFLECTION_KEY;
2829

2930
import java.lang.reflect.Executable;
3031
import java.lang.reflect.Field;
@@ -207,13 +208,18 @@ public void afterRegistration(AfterRegistrationAccess arg) {
207208

208209
ConfigurationConditionResolver<ConfigurationCondition> conditionResolver = new NativeImageConditionResolver(access.getImageClassLoader(),
209210
ClassInitializationSupport.singleton());
210-
ReflectionConfigurationParser<ConfigurationCondition, Class<?>> parser = ConfigurationParserUtils.create(JNI_KEY, true, conditionResolver, runtimeSupport, null, access.getImageClassLoader());
211+
ReflectionConfigurationParser<ConfigurationCondition, Class<?>> parser = ConfigurationParserUtils.create(JNI_KEY, true, conditionResolver, runtimeSupport, null, access.getImageClassLoader(), false);
211212
loadedConfigurations = ConfigurationParserUtils.parseAndRegisterConfigurationsFromCombinedFile(parser, access.getImageClassLoader(), "JNI");
213+
ReflectionConfigurationParser<ConfigurationCondition, Class<?>> reflectParser = ConfigurationParserUtils.create(REFLECTION_KEY, true, conditionResolver, runtimeSupport, null, access.getImageClassLoader(), true);
214+
loadedConfigurations += ConfigurationParserUtils.parseAndRegisterConfigurationsFromCombinedFile(reflectParser, access.getImageClassLoader(), "Reflection");
212215
ReflectionConfigurationParser<ConfigurationCondition, Class<?>> legacyParser = ConfigurationParserUtils.create(null, false, conditionResolver, runtimeSupport, null,
213-
access.getImageClassLoader());
216+
access.getImageClassLoader(), false);
214217
loadedConfigurations += ConfigurationParserUtils.parseAndRegisterConfigurations(legacyParser, access.getImageClassLoader(), "JNI",
215218
ConfigurationFiles.Options.JNIConfigurationFiles, ConfigurationFiles.Options.JNIConfigurationResources, ConfigurationFile.JNI.getFileName());
216-
}
219+
ReflectionConfigurationParser<ConfigurationCondition, Class<?>> legacyRefectionParser = ConfigurationParserUtils.create(null, false, conditionResolver, runtimeSupport, null,
220+
access.getImageClassLoader(), true);
221+
loadedConfigurations += ConfigurationParserUtils.parseAndRegisterConfigurations(legacyRefectionParser, access.getImageClassLoader(), "Reflection",
222+
ConfigurationFiles.Options.ReflectionConfigurationFiles, ConfigurationFiles.Options.ReflectionConfigurationResources, ConfigurationFile.REFLECTION.getFileName()); }
217223

218224
private class JNIRuntimeAccessibilitySupportImpl extends ConditionalConfigurationRegistry
219225
implements RuntimeJNIAccessSupport {

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionFeature.java

+11-2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
*/
2525
package com.oracle.svm.hosted.reflect;
2626

27+
import static com.oracle.svm.core.configure.ConfigurationParser.JNI_KEY;
2728
import static com.oracle.svm.core.configure.ConfigurationParser.REFLECTION_KEY;
2829

2930
import java.lang.invoke.MethodHandle;
@@ -281,13 +282,21 @@ public void duringSetup(DuringSetupAccess a) {
281282
reflectionData.duringSetup(access.getMetaAccess(), aUniverse);
282283
ProxyRegistry proxyRegistry = ImageSingletons.lookup(ProxyRegistry.class);
283284
ReflectionConfigurationParser<ConfigurationCondition, Class<?>> parser = ConfigurationParserUtils.create(REFLECTION_KEY, true, conditionResolver, reflectionData, proxyRegistry,
284-
access.getImageClassLoader());
285+
access.getImageClassLoader(), false);
285286
loadedConfigurations = ConfigurationParserUtils.parseAndRegisterConfigurationsFromCombinedFile(parser, access.getImageClassLoader(), "reflection");
287+
ReflectionConfigurationParser<ConfigurationCondition, Class<?>> jniParser = ConfigurationParserUtils.create(JNI_KEY, true, conditionResolver, reflectionData, proxyRegistry,
288+
access.getImageClassLoader(), false);
289+
loadedConfigurations += ConfigurationParserUtils.parseAndRegisterConfigurationsFromCombinedFile(jniParser, access.getImageClassLoader(), "JNI");
286290
ReflectionConfigurationParser<ConfigurationCondition, Class<?>> legacyParser = ConfigurationParserUtils.create(null, false, conditionResolver, reflectionData, proxyRegistry,
287-
access.getImageClassLoader());
291+
access.getImageClassLoader(), false);
288292
loadedConfigurations += ConfigurationParserUtils.parseAndRegisterConfigurations(legacyParser, access.getImageClassLoader(), "reflection",
289293
ConfigurationFiles.Options.ReflectionConfigurationFiles, ConfigurationFiles.Options.ReflectionConfigurationResources,
290294
ConfigurationFile.REFLECTION.getFileName());
295+
ReflectionConfigurationParser<ConfigurationCondition, Class<?>> legacyJNIParser = ConfigurationParserUtils.create(null, false, conditionResolver, reflectionData, proxyRegistry,
296+
access.getImageClassLoader(), false);
297+
loadedConfigurations += ConfigurationParserUtils.parseAndRegisterConfigurations(legacyJNIParser, access.getImageClassLoader(), "JNI",
298+
ConfigurationFiles.Options.JNIConfigurationFiles, ConfigurationFiles.Options.JNIConfigurationResources,
299+
ConfigurationFile.JNI.getFileName());
291300

292301
loader = access.getImageClassLoader();
293302
annotationSubstitutions = ((Inflation) access.getBigBang()).getAnnotationSubstitutionProcessor();

0 commit comments

Comments
 (0)