Skip to content

Commit 3bc9532

Browse files
committed
Avoid tracing accesses triggered by shutdown hook
1 parent 75fd53a commit 3bc9532

File tree

4 files changed

+73
-14
lines changed

4 files changed

+73
-14
lines changed

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import org.graalvm.nativeimage.impl.ConfigurationCondition;
4242

4343
import com.oracle.svm.configure.ClassNameSupport;
44+
import com.oracle.svm.configure.config.ConfigurationType;
4445
import com.oracle.svm.core.configure.ConditionalRuntimeValue;
4546
import com.oracle.svm.core.configure.RuntimeConditionSet;
4647
import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton;
@@ -453,7 +454,10 @@ public static boolean canUnsafeInstantiateAsInstance(DynamicHub hub) {
453454
}
454455
if (conditionSet != null) {
455456
if (MetadataTracer.Options.MetadataTracingSupport.getValue() && MetadataTracer.singleton().enabled()) {
456-
MetadataTracer.singleton().traceReflectionType(clazz.getName()).setUnsafeAllocated();
457+
ConfigurationType type = MetadataTracer.singleton().traceReflectionType(clazz.getName());
458+
if (type != null) {
459+
type.setUnsafeAllocated();
460+
}
457461
}
458462
return conditionSet.satisfied();
459463
}

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

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,9 @@ private static boolean isClassFlagSet(int mask, ReflectionMetadata reflectionMet
736736

737737
private void traceClassFlagQuery(int mask) {
738738
ConfigurationType type = MetadataTracer.singleton().traceReflectionType(getName());
739+
if (type == null) {
740+
return;
741+
}
739742
// TODO (GR-64765): We over-approximate member accessibility here because we don't trace
740743
// accesses. Once we trace accesses, it will suffice to register the class for reflection.
741744
switch (mask) {
@@ -1344,13 +1347,17 @@ private void traceFieldLookup(String fieldName, Field field, boolean publicOnly)
13441347
if (field != null) {
13451348
// register declaring type and field
13461349
ConfigurationType declaringType = MetadataTracer.singleton().traceReflectionType(field.getDeclaringClass().getName());
1347-
declaringType.addField(fieldName, declaration, false);
1350+
if (declaringType != null) {
1351+
declaringType.addField(fieldName, declaration, false);
1352+
}
13481353
// register receiver type
13491354
MetadataTracer.singleton().traceReflectionType(getName());
13501355
} else {
13511356
// register receiver type and negative field query
13521357
ConfigurationType receiverType = MetadataTracer.singleton().traceReflectionType(getName());
1353-
receiverType.addField(fieldName, declaration, false);
1358+
if (receiverType != null) {
1359+
receiverType.addField(fieldName, declaration, false);
1360+
}
13541361
}
13551362
}
13561363

@@ -1425,13 +1432,17 @@ private void traceMethodLookup(String methodName, Class<?>[] parameterTypes, Exe
14251432
if (method != null) {
14261433
// register declaring type and method
14271434
ConfigurationType declaringType = MetadataTracer.singleton().traceReflectionType(method.getDeclaringClass().getName());
1428-
declaringType.addMethod(methodName, toInternalSignature(parameterTypes), declaration);
1435+
if (declaringType != null) {
1436+
declaringType.addMethod(methodName, toInternalSignature(parameterTypes), declaration);
1437+
}
14291438
// register receiver type
14301439
MetadataTracer.singleton().traceReflectionType(getName());
14311440
} else {
14321441
// register receiver type and negative method query
14331442
ConfigurationType receiverType = MetadataTracer.singleton().traceReflectionType(getName());
1434-
receiverType.addMethod(methodName, toInternalSignature(parameterTypes), declaration, ConfigurationMemberAccessibility.QUERIED);
1443+
if (receiverType != null) {
1444+
receiverType.addMethod(methodName, toInternalSignature(parameterTypes), declaration, ConfigurationMemberAccessibility.QUERIED);
1445+
}
14351446
}
14361447
}
14371448

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,9 @@ private static JNIAccessibleMethod getDeclaredMethod(Class<?> classObject, JNIAc
282282
if (method != null) {
283283
if (MetadataTracer.Options.MetadataTracingSupport.getValue() && MetadataTracer.singleton().enabled()) {
284284
ConfigurationType clazzType = MetadataTracer.singleton().traceJNIType(classObject.getName());
285-
clazzType.addMethod(descriptor.getNameConvertToString(), descriptor.getSignatureConvertToString(), ConfigurationMemberInfo.ConfigurationMemberDeclaration.DECLARED);
285+
if (clazzType != null) {
286+
clazzType.addMethod(descriptor.getNameConvertToString(), descriptor.getSignatureConvertToString(), ConfigurationMemberInfo.ConfigurationMemberDeclaration.DECLARED);
287+
}
286288
}
287289
return method;
288290
}
@@ -341,7 +343,9 @@ private static JNIAccessibleField getDeclaredField(Class<?> classObject, CharSeq
341343
if (field != null && (field.isStatic() == isStatic || field.isNegative())) {
342344
if (MetadataTracer.Options.MetadataTracingSupport.getValue() && MetadataTracer.singleton().enabled()) {
343345
ConfigurationType clazzType = MetadataTracer.singleton().traceJNIType(classObject.getName());
344-
clazzType.addField(name.toString(), ConfigurationMemberInfo.ConfigurationMemberDeclaration.DECLARED, false);
346+
if (clazzType != null) {
347+
clazzType.addField(name.toString(), ConfigurationMemberInfo.ConfigurationMemberDeclaration.DECLARED, false);
348+
}
345349
}
346350
return field;
347351
}

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

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public static class Options {
6868
public static final RuntimeOptionKey<String> RecordMetadata = new RuntimeOptionKey<>("");
6969
}
7070

71-
private ConfigurationSet config;
71+
private volatile ConfigurationSet config;
7272

7373
private Path recordMetadataPath;
7474

@@ -77,11 +77,20 @@ public static MetadataTracer singleton() {
7777
return ImageSingletons.lookup(MetadataTracer.class);
7878
}
7979

80+
/**
81+
* Returns whether tracing is enabled at run time (using {@code -XX:RecordMetadata=path}).
82+
*/
8083
public boolean enabled() {
8184
VMError.guarantee(Options.MetadataTracingSupport.getValue());
82-
return config != null;
85+
return recordMetadataPath != null;
8386
}
8487

88+
/**
89+
* Marks the given type as reachable from reflection.
90+
*
91+
* @return the corresponding {@link ConfigurationType} or {@code null} if tracing is not active
92+
* (e.g., during shutdown).
93+
*/
8594
public ConfigurationType traceReflectionType(String className) {
8695
return traceReflectionTypeImpl(new NamedConfigurationTypeDescriptor(className));
8796
}
@@ -95,29 +104,59 @@ public void traceProxyType(List<String> interfaceNames) {
95104

96105
private ConfigurationType traceReflectionTypeImpl(ConfigurationTypeDescriptor typeDescriptor) {
97106
assert enabled();
98-
return config.getReflectionConfiguration().getOrCreateType(UnresolvedConfigurationCondition.alwaysTrue(), new NamedConfigurationTypeDescriptor(className));
107+
ConfigurationSet configurationSet = config;
108+
if (configurationSet != null) {
109+
return configurationSet.getReflectionConfiguration().getOrCreateType(UnresolvedConfigurationCondition.alwaysTrue(), typeDescriptor);
110+
}
111+
return null;
99112
}
100113

114+
/**
115+
* Marks the given type as reachable from JNI.
116+
*
117+
* @return the corresponding {@link ConfigurationType} or {@code null} if tracing is not active
118+
* (e.g., during shutdown).
119+
*/
101120
public ConfigurationType traceJNIType(String className) {
102121
assert enabled();
103122
ConfigurationType result = traceReflectionType(className);
104-
result.setJniAccessible();
123+
if (result != null) {
124+
result.setJniAccessible();
125+
}
105126
return result;
106127
}
107128

129+
/**
130+
* Marks the given resource within the given (optional) module as reachable.
131+
*/
108132
public void traceResource(String resourceName, String moduleName) {
109133
assert enabled();
110-
config.getResourceConfiguration().addGlobPattern(UnresolvedConfigurationCondition.alwaysTrue(), resourceName, moduleName);
134+
ConfigurationSet configurationSet = config;
135+
if (configurationSet != null) {
136+
configurationSet.getResourceConfiguration().addGlobPattern(UnresolvedConfigurationCondition.alwaysTrue(), resourceName, moduleName);
137+
}
111138
}
112139

140+
/**
141+
* Marks the given resource bundle within the given locale as reachable.
142+
*/
113143
public void traceResourceBundle(String baseName) {
114144
assert enabled();
115-
config.getResourceConfiguration().addBundle(UnresolvedConfigurationCondition.alwaysTrue(), baseName, List.of());
145+
ConfigurationSet configurationSet = config;
146+
if (configurationSet != null) {
147+
configurationSet.getResourceConfiguration().addBundle(UnresolvedConfigurationCondition.alwaysTrue(), baseName, List.of());
148+
}
116149
}
117150

151+
/**
152+
* Marks the given type as serializable.
153+
*/
118154
public void traceSerializationType(String className) {
119155
assert enabled();
120-
traceReflectionType(className).setSerializable();
156+
ConfigurationType result = traceReflectionType(className);
157+
if (result != null) {
158+
result.setSerializable();
159+
}
121160
}
122161

123162
private static void initialize() {
@@ -141,6 +180,7 @@ private static void shutdown() {
141180
assert Options.MetadataTracingSupport.getValue();
142181
MetadataTracer singleton = MetadataTracer.singleton();
143182
ConfigurationSet config = singleton.config;
183+
singleton.config = null; // clear config so that shutdown events are not traced.
144184
if (config != null) {
145185
try {
146186
config.writeConfiguration(configFile -> singleton.recordMetadataPath.resolve(configFile.getFileName()));

0 commit comments

Comments
 (0)