Skip to content

Commit ee126fe

Browse files
committed
[GR-62575] Eagerly initialize JdkCatalog#catalog before analysis
PullRequest: graal/20234
2 parents 7fe6c24 + 48b3438 commit ee126fe

File tree

2 files changed

+31
-35
lines changed

2 files changed

+31
-35
lines changed

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/xml/Target_jdk_xml_internal_JdkCatalog.java

Lines changed: 6 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,15 @@
2424
*/
2525
package com.oracle.svm.core.jdk.xml;
2626

27-
import java.time.Duration;
2827
import java.util.Objects;
2928

30-
import com.oracle.svm.core.util.VMError;
3129
import org.graalvm.nativeimage.hosted.FieldValueTransformer;
3230

3331
import com.oracle.svm.core.annotate.Alias;
3432
import com.oracle.svm.core.annotate.RecomputeFieldValue;
3533
import com.oracle.svm.core.annotate.Substitute;
3634
import com.oracle.svm.core.annotate.TargetClass;
3735
import com.oracle.svm.core.jdk.JDKLatest;
38-
import com.oracle.svm.util.ReflectionUtil;
3936

4037
/**
4138
* Substitution to initialize {@link #catalog} at build time.
@@ -78,38 +75,13 @@ final class Target_javax_xml_parsers_SAXParser {
7875

7976
final class JdkCatalogSupplier implements FieldValueTransformer {
8077

81-
private static Object catalog;
82-
83-
private static synchronized Object getCatalog() {
84-
// Ensure the field is initialized.
85-
Class<?> xmlSecurityManager = ReflectionUtil.lookupClass(false, "jdk.xml.internal.XMLSecurityManager");
86-
// The constructor call prepareCatalog which will call JdkCatalog#init.
87-
ReflectionUtil.newInstance(xmlSecurityManager);
88-
89-
try {
90-
/*
91-
* Workaround for race condition in XMLSecurityManager#prepareCatalog (JDK-8350189).
92-
*/
93-
for (int retryCount = 0; catalog == null && retryCount < 3; retryCount++) {
94-
Class<?> jdkCatalogClass = ReflectionUtil.lookupClass(false, "jdk.xml.internal.JdkCatalog");
95-
Object res = ReflectionUtil.readStaticField(jdkCatalogClass, "catalog");
96-
if (res == null) {
97-
Thread.sleep(Duration.ofMillis(100));
98-
continue;
99-
}
100-
catalog = res;
101-
}
102-
} catch (InterruptedException e) {
103-
/* fall-through to the null check */
104-
}
105-
if (catalog == null) {
106-
throw VMError.shouldNotReachHere("JdkCatalog initialization failed");
107-
}
108-
return catalog;
109-
}
110-
78+
/**
79+
* Verifies that {@link Target_jdk_xml_internal_JdkCatalog#catalog} is non-null. The
80+
* initialization is triggered in
81+
* {@code com.oracle.svm.hosted.xml.JavaxXmlClassAndResourcesLoaderFeature#initializeJdkCatalog()}
82+
*/
11183
@Override
11284
public Object transform(Object receiver, Object originalValue) {
113-
return Objects.requireNonNull(getCatalog());
85+
return Objects.requireNonNull(originalValue, "JdkCatalog initialization failed");
11486
}
11587
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/xml/JavaxXmlClassAndResourcesLoaderFeature.java

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,14 @@
3434
import static com.oracle.svm.hosted.xml.XMLParsersRegistration.StAXParserClasses;
3535
import static com.oracle.svm.hosted.xml.XMLParsersRegistration.TransformerClassesAndResources;
3636

37+
import org.graalvm.nativeimage.hosted.FieldValueTransformer;
38+
39+
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
3740
import com.oracle.svm.core.feature.InternalFeature;
3841
import com.oracle.svm.core.jdk.JNIRegistrationUtil;
39-
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
42+
import com.oracle.svm.util.ReflectionUtil;
43+
44+
import jdk.graal.compiler.serviceprovider.JavaVersionUtil;
4045

4146
@AutomaticallyRegisteredFeature
4247
public class JavaxXmlClassAndResourcesLoaderFeature extends JNIRegistrationUtil implements InternalFeature {
@@ -66,5 +71,24 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
6671

6772
access.registerReachabilityHandler(new BuiltinSchemaGrammarClasses()::registerConfigs,
6873
constructor(access, "com.sun.org.apache.xerces.internal.impl.xs.SchemaGrammar$BuiltinSchemaGrammar", int.class, short.class));
74+
75+
initializeJdkCatalog();
76+
}
77+
78+
/**
79+
* Initialize the {@code JdkCatalog#catalog} field. We do this eagerly (instead of e.g. in a
80+
* {@link FieldValueTransformer}) to work around a race condition in
81+
* XMLSecurityManager#prepareCatalog (JDK-8350189).
82+
*/
83+
private static void initializeJdkCatalog() {
84+
if (JavaVersionUtil.JAVA_SPEC <= 21) {
85+
return;
86+
}
87+
if (ModuleLayer.boot().findModule("java.xml").isPresent()) {
88+
// Ensure the JdkCatalog#catalog field is initialized.
89+
Class<?> xmlSecurityManager = ReflectionUtil.lookupClass(false, "jdk.xml.internal.XMLSecurityManager");
90+
// The constructor call prepareCatalog which will call JdkCatalog#init.
91+
ReflectionUtil.newInstance(xmlSecurityManager);
92+
}
6993
}
7094
}

0 commit comments

Comments
 (0)