Skip to content

Commit 4f9263d

Browse files
committed
Futher refine CustomGraalClassLoader support for libgraal building
1 parent c31b058 commit 4f9263d

File tree

14 files changed

+174
-149
lines changed

14 files changed

+174
-149
lines changed

compiler/src/jdk.graal.compiler.libgraal.loader/src/jdk/graal/compiler/hotspot/libgraal/LibGraalClassLoader.java

+29-51
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,13 @@
3838
import java.nio.file.Path;
3939
import java.security.ProtectionDomain;
4040
import java.util.ArrayList;
41+
import java.util.Collections;
4142
import java.util.Enumeration;
4243
import java.util.HashMap;
4344
import java.util.List;
4445
import java.util.Map;
45-
import java.util.NoSuchElementException;
4646
import java.util.Objects;
4747
import java.util.Set;
48-
import java.util.function.Consumer;
4948

5049
import org.graalvm.nativeimage.Platform;
5150
import org.graalvm.nativeimage.Platforms;
@@ -59,8 +58,9 @@
5958
/**
6059
* A classloader, that reads class files and resources from a jimage file at image build time.
6160
*/
61+
@SuppressWarnings("unused")
6262
@Platforms(Platform.HOSTED_ONLY.class)
63-
final class HostedLibGraalClassLoader extends ClassLoader {
63+
final class HostedLibGraalClassLoader extends ClassLoader implements LibGraalClassLoaderBase {
6464

6565
private static final String JAVA_HOME_PROPERTY_KEY = "jdk.graal.internal.libgraal.javahome";
6666
private static final String JAVA_HOME_PROPERTY_VALUE = System.getProperty(JAVA_HOME_PROPERTY_KEY, System.getProperty("java.home"));
@@ -79,7 +79,7 @@ final class HostedLibGraalClassLoader extends ClassLoader {
7979
* Map from the {@linkplain Class#forName(String) name} of a class to the image path of its
8080
* class file.
8181
*/
82-
private final Map<String, String> classes = new HashMap<>();
82+
private final Map<String, String> classes;
8383

8484
/**
8585
* Map from a service name to a list of providers.
@@ -113,7 +113,6 @@ public HostedLibGraalClassLoader() {
113113
super(LibGraalClassLoader.LOADER_NAME, Feature.class.getClassLoader());
114114
libGraalJavaHome = Path.of(JAVA_HOME_PROPERTY_VALUE);
115115

116-
Map<String, String> modulesMap = new HashMap<>();
117116
try {
118117
/*
119118
* Access to jdk.internal.jimage classes is needed by this Classloader implementation.
@@ -129,6 +128,9 @@ public HostedLibGraalClassLoader() {
129128
Modules.addExports(javaBaseModule, "jdk.internal.vm", unnamedModuleOfThisLoader);
130129
Modules.addExports(javaBaseModule, "jdk.internal.misc", unnamedModuleOfThisLoader);
131130

131+
Map<String, String> modulesMap = new HashMap<>();
132+
Map<String, String> classesMap = new HashMap<>();
133+
132134
Path imagePath = libGraalJavaHome.resolve(Path.of("lib", "modules"));
133135
this.imageReader = BasicImageReader.open(imagePath);
134136
for (var entry : imageReader.getEntryNames()) {
@@ -140,50 +142,38 @@ public HostedLibGraalClassLoader() {
140142
resources.put(resource, entry);
141143
if (resource.endsWith(".class")) {
142144
String className = resource.substring(0, resource.length() - ".class".length()).replace('/', '.');
143-
classes.put(className, entry);
144145
if (resource.equals("module-info.class")) {
145146
ModuleDescriptor md = ModuleDescriptor.read(imageReader.getResourceBuffer(imageReader.findLocation(entry)));
146147
for (var p : md.provides()) {
147148
services.computeIfAbsent(p.service(), k -> new ArrayList<>()).addAll(p.providers());
148149
}
149150
} else {
151+
classesMap.put(className, entry);
150152
modulesMap.put(className, module);
151153
}
152154
}
153155
}
154156
}
155157
}
156158

159+
modules = Map.copyOf(modulesMap);
160+
classes = Map.copyOf(classesMap);
161+
157162
} catch (IOException e) {
158-
throw new RuntimeException(e);
163+
throw GraalError.shouldNotReachHere(e);
159164
}
160-
this.modules = Map.copyOf(modulesMap);
161165
}
162166

163-
/**
164-
* Gets an unmodifiable map from the {@linkplain Class#forName(String) name} of a class to the
165-
* name of its enclosing module. Reflectively accessed by
166-
* {@code LibGraalFeature.OptionCollector#afterAnalysis(AfterAnalysisAccess)}.
167-
*/
168-
@SuppressWarnings("unused")
167+
@Override
169168
public Map<String, String> getModules() {
170169
return modules;
171170
}
172171

173172
/* Allow image builder to perform registration action on each class this loader provides. */
174-
@SuppressWarnings("unused")
175-
public void forEachClass(Consumer<Class<?>> action) {
176-
for (String className : classes.keySet()) {
177-
if (className.equals("module-info")) {
178-
continue;
179-
}
180-
try {
181-
var clazz = loadClass(className);
182-
action.accept(clazz);
183-
} catch (ClassNotFoundException e) {
184-
throw GraalError.shouldNotReachHere(e, LibGraalClassLoader.LOADER_NAME + " could not load class " + className);
185-
}
186-
}
173+
174+
@Override
175+
public Set<String> getAllClassNames() {
176+
return classes.keySet();
187177
}
188178

189179
@Override
@@ -262,24 +252,11 @@ protected URL findResource(String name) {
262252

263253
@Override
264254
protected Enumeration<URL> findResources(String name) throws IOException {
265-
return new Enumeration<>() {
266-
private URL next = findResource(name);
267-
268-
@Override
269-
public boolean hasMoreElements() {
270-
return (next != null);
271-
}
272-
273-
@Override
274-
public URL nextElement() {
275-
if (next == null) {
276-
throw new NoSuchElementException();
277-
}
278-
URL u = next;
279-
next = null;
280-
return u;
281-
}
282-
};
255+
URL resource = findResource(name);
256+
if (resource == null) {
257+
return Collections.emptyEnumeration();
258+
}
259+
return Collections.enumeration(List.of(resource));
283260
}
284261

285262
/**
@@ -340,12 +317,13 @@ public String getContentType() {
340317
}
341318
}
342319

343-
/**
344-
* @return instance of ClassLoader that should be seen at image-runtime if a class was loaded at
345-
* image-buildtime by this classloader.
346-
*/
347-
@SuppressWarnings("unused")
348-
public static ClassLoader getRuntimeClassLoader() {
320+
@Override
321+
public HostedLibGraalClassLoader getClassLoader() {
322+
return this;
323+
}
324+
325+
@Override
326+
public LibGraalClassLoader getRuntimeClassLoader() {
349327
return LibGraalClassLoader.singleton;
350328
}
351329
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -23,22 +23,32 @@
2323
* questions.
2424
*/
2525

26-
package com.oracle.svm.hosted;
26+
package jdk.graal.compiler.hotspot.libgraal;
2727

28-
import org.graalvm.nativeimage.ImageSingletons;
28+
import java.util.Map;
29+
import java.util.Set;
2930

30-
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
31-
import com.oracle.svm.core.feature.InternalFeature;
32-
import com.oracle.svm.core.hub.ClassForNameSupport;
33-
import com.oracle.svm.core.layeredimagesingleton.FeatureSingleton;
34-
import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton;
35-
import com.oracle.svm.hosted.FeatureImpl.AfterRegistrationAccessImpl;
31+
public interface LibGraalClassLoaderBase {
3632

37-
@AutomaticallyRegisteredFeature
38-
public final class ClassForNameSupportFeature implements InternalFeature, FeatureSingleton, UnsavedSingleton {
39-
@Override
40-
public void afterRegistration(AfterRegistrationAccess access) {
41-
ClassLoader customLoader = ((AfterRegistrationAccessImpl) access).getImageClassLoader().classLoaderSupport.getCustomLoader();
42-
ImageSingletons.add(ClassForNameSupport.class, new ClassForNameSupport(customLoader));
43-
}
33+
/**
34+
* @return instance of ClassLoader that implements this interface.
35+
*/
36+
ClassLoader getClassLoader();
37+
38+
/**
39+
* @return instance of ClassLoader that should be seen at image-runtime if a class was loaded at
40+
* image-buildtime by this classloader.
41+
*/
42+
ClassLoader getRuntimeClassLoader();
43+
44+
/**
45+
* Gets an unmodifiable map from the {@linkplain Class#forName(String) name} of a class to the
46+
* name of its enclosing module.
47+
*/
48+
Map<String, String> getModules();
49+
50+
/**
51+
* Get unmodifiable set of fully qualified names of all classes this loader can load.
52+
*/
53+
Set<String> getAllClassNames();
4454
}

substratevm/mx.substratevm/mx_substratevm.py

+1
Original file line numberDiff line numberDiff line change
@@ -1508,6 +1508,7 @@ def prevent_build_path_in_libgraal():
15081508

15091509
## Pass via JVM args opening up of packages needed for image builder early on
15101510
'-J--add-exports=jdk.graal.compiler/jdk.graal.compiler.hotspot=ALL-UNNAMED',
1511+
'-J--add-exports=jdk.graal.compiler/jdk.graal.compiler.hotspot.libgraal=ALL-UNNAMED',
15111512
'-J--add-exports=jdk.graal.compiler/jdk.graal.compiler.options=ALL-UNNAMED',
15121513
'-J--add-exports=jdk.graal.compiler/jdk.graal.compiler.truffle=ALL-UNNAMED',
15131514
'-J--add-exports=jdk.graal.compiler/jdk.graal.compiler.truffle.hotspot=ALL-UNNAMED',

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

+6-8
Original file line numberDiff line numberDiff line change
@@ -38,23 +38,21 @@
3838

3939
import com.oracle.svm.core.configure.ConditionalRuntimeValue;
4040
import com.oracle.svm.core.configure.RuntimeConditionSet;
41+
import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton;
4142
import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags;
4243
import com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton;
4344
import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton;
4445
import com.oracle.svm.core.reflect.MissingReflectionRegistrationUtils;
4546
import com.oracle.svm.core.util.ImageHeapMap;
4647
import com.oracle.svm.core.util.VMError;
4748

49+
@AutomaticallyRegisteredImageSingleton
4850
public final class ClassForNameSupport implements MultiLayeredImageSingleton, UnsavedSingleton {
4951

50-
private ClassLoader customLoader;
52+
private ClassLoader libGraalLoader;
5153

52-
public ClassForNameSupport(ClassLoader customLoader) {
53-
setCustomLoader(customLoader);
54-
}
55-
56-
public void setCustomLoader(ClassLoader customLoader) {
57-
this.customLoader = customLoader;
54+
public void setLibGraalLoader(ClassLoader libGraalLoader) {
55+
this.libGraalLoader = libGraalLoader;
5856
}
5957

6058
public static ClassForNameSupport singleton() {
@@ -126,7 +124,7 @@ accessible through the builder class loader, and it was already registered by na
126124

127125
@Platforms(HOSTED_ONLY.class)
128126
private boolean isLibGraalClass(Class<?> clazz) {
129-
return customLoader != null && clazz.getClassLoader() == customLoader;
127+
return libGraalLoader != null && clazz.getClassLoader() == libGraalLoader;
130128
}
131129

132130
public static ConditionalRuntimeValue<Object> updateConditionalValue(ConditionalRuntimeValue<Object> existingConditionalValue, Object newValue,

substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFeature.java

+9-6
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@
6262
import com.oracle.svm.core.util.VMError;
6363
import com.oracle.svm.graal.hotspot.GetCompilerConfig;
6464
import com.oracle.svm.graal.hotspot.GetJNIConfig;
65-
import com.oracle.svm.hosted.ClassLoaderFeature;
6665
import com.oracle.svm.hosted.FeatureImpl.AfterAnalysisAccessImpl;
6766
import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl;
6867
import com.oracle.svm.hosted.FeatureImpl.DuringAnalysisAccessImpl;
@@ -74,6 +73,7 @@
7473
import jdk.graal.compiler.debug.DebugContext;
7574
import jdk.graal.compiler.hotspot.CompilerConfigurationFactory;
7675
import jdk.graal.compiler.hotspot.libgraal.BuildTime;
76+
import jdk.graal.compiler.hotspot.libgraal.LibGraalClassLoaderBase;
7777
import jdk.graal.compiler.nodes.graphbuilderconf.GeneratedInvocationPlugin;
7878
import jdk.graal.compiler.options.OptionDescriptor;
7979
import jdk.graal.compiler.options.OptionKey;
@@ -111,6 +111,8 @@ public List<Class<? extends Feature>> getRequiredFeatures() {
111111

112112
final MethodHandles.Lookup mhl = MethodHandles.lookup();
113113

114+
LibGraalClassLoaderBase libGraalClassLoader;
115+
114116
/**
115117
* Loader used for loading classes from the guest GraalVM.
116118
*/
@@ -185,8 +187,9 @@ public void afterRegistration(AfterRegistrationAccess access) {
185187
// org.graalvm.nativeimage.impl.IsolateSupport
186188
accessModulesToClass(ModuleSupport.Access.EXPORT, LibGraalFeature.class, "org.graalvm.nativeimage");
187189

188-
loader = createHostedLibGraalClassLoader(access);
189-
ImageSingletons.lookup(ClassForNameSupport.class).setCustomLoader(loader);
190+
libGraalClassLoader = createHostedLibGraalClassLoader(access);
191+
loader = libGraalClassLoader.getClassLoader();
192+
ImageSingletons.lookup(ClassForNameSupport.class).setLibGraalLoader(loader);
190193

191194
buildTimeClass = loadClassOrFail("jdk.graal.compiler.hotspot.libgraal.BuildTime");
192195

@@ -208,10 +211,10 @@ public void afterRegistration(AfterRegistrationAccess access) {
208211
}
209212

210213
@SuppressWarnings("unchecked")
211-
private static ClassLoader createHostedLibGraalClassLoader(AfterRegistrationAccess access) {
214+
private static LibGraalClassLoaderBase createHostedLibGraalClassLoader(AfterRegistrationAccess access) {
212215
var hostedLibGraalClassLoaderClass = access.findClassByName("jdk.graal.compiler.hotspot.libgraal.HostedLibGraalClassLoader");
213216
ModuleSupport.accessPackagesToClass(Access.EXPORT, hostedLibGraalClassLoaderClass, false, "java.base", "jdk.internal.module");
214-
return ReflectionUtil.newInstance((Class<ClassLoader>) hostedLibGraalClassLoaderClass);
217+
return ReflectionUtil.newInstance((Class<LibGraalClassLoaderBase>) hostedLibGraalClassLoaderClass);
215218
}
216219

217220
private static void accessModulesToClass(ModuleSupport.Access access, Class<?> accessingClass, String... moduleNames) {
@@ -233,7 +236,7 @@ public void duringSetup(DuringSetupAccess access) {
233236
* HostedLibGraalClassLoader provides runtime-replacement loader instance. Make sure
234237
* HostedLibGraalClassLoader gets replaced by customRuntimeLoader instance in image.
235238
*/
236-
ClassLoader customRuntimeLoader = ClassLoaderFeature.getCustomRuntimeClassLoader(loader);
239+
ClassLoader customRuntimeLoader = libGraalClassLoader.getRuntimeClassLoader();
237240
access.registerObjectReplacer(obj -> obj == loader ? customRuntimeLoader : obj);
238241

239242
try {

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ClassLoaderFeature.java

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

27-
import java.lang.reflect.Method;
2827
import java.util.concurrent.ConcurrentHashMap;
2928
import java.util.function.Function;
3029

@@ -33,6 +32,7 @@
3332
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
3433
import com.oracle.svm.core.feature.InternalFeature;
3534
import com.oracle.svm.core.fieldvaluetransformer.FieldValueTransformerWithAvailability;
35+
import com.oracle.svm.core.hub.ClassForNameSupport;
3636
import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport;
3737
import com.oracle.svm.core.util.VMError;
3838
import com.oracle.svm.hosted.FeatureImpl.DuringSetupAccessImpl;
@@ -41,6 +41,7 @@
4141
import com.oracle.svm.hosted.jdk.HostedClassLoaderPackageManagement;
4242
import com.oracle.svm.util.ReflectionUtil;
4343

44+
import jdk.graal.compiler.hotspot.libgraal.LibGraalClassLoaderBase;
4445
import jdk.internal.loader.ClassLoaders;
4546
import jdk.vm.ci.meta.JavaConstant;
4647

@@ -120,15 +121,18 @@ public void duringSetup(DuringSetupAccess access) {
120121

121122
var config = (FeatureImpl.DuringSetupAccessImpl) access;
122123
if (ImageLayerBuildingSupport.firstImageBuild()) {
123-
ClassLoader customLoader = ((DuringSetupAccessImpl) access).imageClassLoader.classLoaderSupport.getCustomLoader();
124-
if (customLoader != null) {
125-
ClassLoader customRuntimeLoader = getCustomRuntimeClassLoader(customLoader);
126-
if (customRuntimeLoader != null) {
124+
LibGraalClassLoaderBase libGraalLoader = ((DuringSetupAccessImpl) access).imageClassLoader.classLoaderSupport.getLibGraalLoader();
125+
if (libGraalLoader != null) {
126+
ClassLoader libGraalClassLoader = libGraalLoader.getClassLoader();
127+
ClassForNameSupport.singleton().setLibGraalLoader(libGraalClassLoader);
128+
129+
ClassLoader runtimeLibGraalClassLoader = libGraalLoader.getRuntimeClassLoader();
130+
if (runtimeLibGraalClassLoader != null) {
127131
/*
128-
* CustomLoader provides runtime-replacement ClassLoader instance. Make sure
129-
* customLoader gets replaced by customRuntimeLoader instance in image.
132+
* LibGraalLoader provides runtime-replacement ClassLoader instance. Make sure
133+
* LibGraalLoader gets replaced by runtimeLibGraalClassLoader instance in image.
130134
*/
131-
access.registerObjectReplacer(obj -> obj == customLoader ? customRuntimeLoader : obj);
135+
access.registerObjectReplacer(obj -> obj == libGraalClassLoader ? runtimeLibGraalClassLoader : obj);
132136
}
133137
}
134138
access.registerObjectReplacer(this::runtimeClassLoaderObjectReplacer);
@@ -146,12 +150,6 @@ public void duringSetup(DuringSetupAccess access) {
146150
}
147151
}
148152

149-
public static ClassLoader getCustomRuntimeClassLoader(ClassLoader customLoader) {
150-
Class<? extends ClassLoader> customLoaderClass = customLoader.getClass();
151-
Method getRuntimeClassLoaderMethod = ReflectionUtil.lookupMethod(true, customLoaderClass, "getRuntimeClassLoader");
152-
return getRuntimeClassLoaderMethod != null ? ReflectionUtil.invokeMethod(getRuntimeClassLoaderMethod, null) : null;
153-
}
154-
155153
@Override
156154
public void beforeAnalysis(BeforeAnalysisAccess access) {
157155
var packagesField = ReflectionUtil.lookupField(ClassLoader.class, "packages");

0 commit comments

Comments
 (0)