Skip to content

Commit c4033bf

Browse files
committed
Avoid tracing accesses triggered by shutdown hook
1 parent 82a41e5 commit c4033bf

File tree

4 files changed

+67
-12
lines changed

4 files changed

+67
-12
lines changed

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/ClassForNameSupport.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.graalvm.nativeimage.impl.ConfigurationCondition;
3838

3939
import com.oracle.svm.configure.ClassNameSupport;
40+
import com.oracle.svm.configure.config.ConfigurationType;
4041
import com.oracle.svm.core.configure.ConditionalRuntimeValue;
4142
import com.oracle.svm.core.configure.RuntimeConditionSet;
4243
import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton;
@@ -302,7 +303,10 @@ public static boolean canUnsafeInstantiateAsInstance(DynamicHub hub) {
302303
}
303304
if (conditionSet != null) {
304305
if (MetadataTracer.Options.MetadataTracingSupport.getValue() && MetadataTracer.singleton().enabled()) {
305-
MetadataTracer.singleton().traceReflectionType(clazz.getName()).setUnsafeAllocated();
306+
ConfigurationType type = MetadataTracer.singleton().traceReflectionType(clazz.getName());
307+
if (type != null) {
308+
type.setUnsafeAllocated();
309+
}
306310
}
307311
return conditionSet.satisfied();
308312
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java

+9-2
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,9 @@ private static boolean isClassFlagSet(int mask, ReflectionMetadata reflectionMet
730730

731731
private void traceClassFlagQuery(int mask) {
732732
ConfigurationType type = MetadataTracer.singleton().traceReflectionType(getName());
733+
if (type == null) {
734+
return;
735+
}
733736
switch (mask) {
734737
case ALL_FIELDS_FLAG -> type.setAllPublicFields(ConfigurationMemberAccessibility.ACCESSED);
735738
case ALL_DECLARED_FIELDS_FLAG -> type.setAllDeclaredFields(ConfigurationMemberAccessibility.ACCESSED);
@@ -1317,7 +1320,9 @@ private void checkField(String fieldName, Field field, boolean publicOnly) throw
13171320
ConfigurationMemberDeclaration declaration = publicOnly ? ConfigurationMemberDeclaration.PRESENT : ConfigurationMemberDeclaration.DECLARED;
13181321
// register declaring type and field
13191322
ConfigurationType declaringType = MetadataTracer.singleton().traceReflectionType(field.getDeclaringClass().getName());
1320-
declaringType.addField(fieldName, declaration, false);
1323+
if (declaringType != null) {
1324+
declaringType.addField(fieldName, declaration, false);
1325+
}
13211326
// register receiver type
13221327
MetadataTracer.singleton().traceReflectionType(getName());
13231328
}
@@ -1392,7 +1397,9 @@ private boolean checkExecutableExists(String methodName, Class<?>[] parameterTyp
13921397
ConfigurationMemberDeclaration declaration = publicOnly ? ConfigurationMemberDeclaration.PRESENT : ConfigurationMemberDeclaration.DECLARED;
13931398
// register declaring type and method
13941399
ConfigurationType declaringType = MetadataTracer.singleton().traceReflectionType(method.getDeclaringClass().getName());
1395-
declaringType.addMethod(methodName, toInternalSignature(parameterTypes), declaration);
1400+
if (declaringType != null) {
1401+
declaringType.addMethod(methodName, toInternalSignature(parameterTypes), declaration);
1402+
}
13961403
// register receiver type
13971404
MetadataTracer.singleton().traceReflectionType(getName());
13981405
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/access/JNIReflectionDictionary.java

+6-2
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,9 @@ private static JNIAccessibleMethod getDeclaredMethod(Class<?> classObject, JNIAc
287287
if (method != null) {
288288
if (MetadataTracer.Options.MetadataTracingSupport.getValue() && MetadataTracer.singleton().enabled()) {
289289
ConfigurationType clazzType = MetadataTracer.singleton().traceJNIType(classObject.getName());
290-
clazzType.addMethod(descriptor.getNameConvertToString(), descriptor.getSignatureConvertToString(), ConfigurationMemberInfo.ConfigurationMemberDeclaration.DECLARED);
290+
if (clazzType != null) {
291+
clazzType.addMethod(descriptor.getNameConvertToString(), descriptor.getSignatureConvertToString(), ConfigurationMemberInfo.ConfigurationMemberDeclaration.DECLARED);
292+
}
291293
}
292294
return method;
293295
}
@@ -346,7 +348,9 @@ private static JNIAccessibleField getDeclaredField(Class<?> classObject, CharSeq
346348
if (field != null && (field.isStatic() == isStatic || field.isNegative())) {
347349
if (MetadataTracer.Options.MetadataTracingSupport.getValue() && MetadataTracer.singleton().enabled()) {
348350
ConfigurationType clazzType = MetadataTracer.singleton().traceJNIType(classObject.getName());
349-
clazzType.addField(name.toString(), ConfigurationMemberInfo.ConfigurationMemberDeclaration.DECLARED, false);
351+
if (clazzType != null) {
352+
clazzType.addField(name.toString(), ConfigurationMemberInfo.ConfigurationMemberDeclaration.DECLARED, false);
353+
}
350354
}
351355
return field;
352356
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/metadata/MetadataTracer.java

+47-7
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public static class Options {
6666
public static final RuntimeOptionKey<String> RecordMetadata = new RuntimeOptionKey<>("");
6767
}
6868

69-
private ConfigurationSet config;
69+
private volatile ConfigurationSet config;
7070

7171
private Path recordMetadataPath;
7272

@@ -75,36 +75,75 @@ public static MetadataTracer singleton() {
7575
return ImageSingletons.lookup(MetadataTracer.class);
7676
}
7777

78+
/**
79+
* Returns whether tracing is enabled at run time (using {@code -XX:RecordMetadata=path}).
80+
*/
7881
public boolean enabled() {
7982
VMError.guarantee(Options.MetadataTracingSupport.getValue());
80-
return config != null;
83+
return recordMetadataPath != null;
8184
}
8285

86+
/**
87+
* Marks the given type as reachable from reflection.
88+
*
89+
* @return the corresponding {@link ConfigurationType} or {@code null} if tracing is not active
90+
* (e.g., during shutdown).
91+
*/
8392
public ConfigurationType traceReflectionType(String className) {
8493
assert enabled();
85-
return config.getReflectionConfiguration().getOrCreateType(UnresolvedConfigurationCondition.alwaysTrue(), new NamedConfigurationTypeDescriptor(className));
94+
ConfigurationSet configurationSet = config;
95+
if (configurationSet != null) {
96+
return configurationSet.getReflectionConfiguration().getOrCreateType(UnresolvedConfigurationCondition.alwaysTrue(), new NamedConfigurationTypeDescriptor(className));
97+
}
98+
return null;
8699
}
87100

101+
/**
102+
* Marks the given type as reachable from JNI.
103+
*
104+
* @return the corresponding {@link ConfigurationType} or {@code null} if tracing is not active
105+
* (e.g., during shutdown).
106+
*/
88107
public ConfigurationType traceJNIType(String className) {
89108
assert enabled();
90109
ConfigurationType result = traceReflectionType(className);
91-
result.setJniAccessible();
110+
if (result != null) {
111+
result.setJniAccessible();
112+
}
92113
return result;
93114
}
94115

116+
/**
117+
* Marks the given resource within the given (optional) module as reachable.
118+
*/
95119
public void traceResource(String resourceName, String moduleName) {
96120
assert enabled();
97-
config.getResourceConfiguration().addGlobPattern(UnresolvedConfigurationCondition.alwaysTrue(), resourceName, moduleName);
121+
ConfigurationSet configurationSet = config;
122+
if (configurationSet != null) {
123+
configurationSet.getResourceConfiguration().addGlobPattern(UnresolvedConfigurationCondition.alwaysTrue(), resourceName, moduleName);
124+
}
98125
}
99126

127+
/**
128+
* Marks the given resource bundle within the given locale as reachable.
129+
*/
100130
public void traceResourceBundle(String baseName) {
101131
assert enabled();
102-
config.getResourceConfiguration().addBundle(UnresolvedConfigurationCondition.alwaysTrue(), baseName, List.of());
132+
ConfigurationSet configurationSet = config;
133+
if (configurationSet != null) {
134+
configurationSet.getResourceConfiguration().addBundle(UnresolvedConfigurationCondition.alwaysTrue(), baseName, List.of());
135+
}
103136
}
104137

138+
/**
139+
* Marks the given type as serializable.
140+
*/
105141
public void traceSerializationType(String className) {
106142
assert enabled();
107-
config.getReflectionConfiguration().getOrCreateType(UnresolvedConfigurationCondition.alwaysTrue(), new NamedConfigurationTypeDescriptor(className)).setSerializable();
143+
ConfigurationSet configurationSet = config;
144+
if (configurationSet != null) {
145+
configurationSet.getReflectionConfiguration().getOrCreateType(UnresolvedConfigurationCondition.alwaysTrue(), new NamedConfigurationTypeDescriptor(className)).setSerializable();
146+
}
108147
}
109148

110149
private static void initialize() {
@@ -128,6 +167,7 @@ private static void shutdown() {
128167
assert Options.MetadataTracingSupport.getValue();
129168
MetadataTracer singleton = MetadataTracer.singleton();
130169
ConfigurationSet config = singleton.config;
170+
singleton.config = null; // clear config so that shutdown events are not traced.
131171
if (config != null) {
132172
try {
133173
config.writeConfiguration(configFile -> singleton.recordMetadataPath.resolve(configFile.getFileName()));

0 commit comments

Comments
 (0)