Skip to content

Commit accd13d

Browse files
committed
[GR-57627] Allow LibGraalFeature class to be loaded by HostedLibGraalClassLoader.
PullRequest: graal/18691
2 parents 4d4b61d + 45253c7 commit accd13d

File tree

14 files changed

+348
-160
lines changed

14 files changed

+348
-160
lines changed

compiler/mx.compiler/suite.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,22 @@
465465
"workingSets" : "Graal,Test",
466466
"graalCompilerSourceEdition": "ignore",
467467
},
468+
469+
"jdk.graal.compiler.libgraal.loader" : {
470+
"subDir" : "src",
471+
"sourceDirs" : ["src"],
472+
"workingSets" : "Graal",
473+
"javaCompliance" : "21+",
474+
"dependencies" : [
475+
"jdk.graal.compiler",
476+
],
477+
"requiresConcealed" : {
478+
"java.base" : [
479+
"jdk.internal.module",
480+
"jdk.internal.jimage",
481+
],
482+
},
483+
},
468484
},
469485

470486
"distributions" : {
@@ -691,6 +707,17 @@
691707
"graalCompilerSourceEdition": "ignore",
692708
},
693709

710+
"LIBGRAAL_LOADER" : {
711+
"subDir": "src",
712+
"dependencies" : [
713+
"jdk.graal.compiler.libgraal.loader",
714+
],
715+
"distDependencies" : [
716+
"GRAAL",
717+
],
718+
"maven": False,
719+
},
720+
694721
"GRAAL_PROFDIFF_TEST" : {
695722
"subDir" : "src",
696723
"dependencies" : [
Lines changed: 103 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
* or visit www.oracle.com if you need additional information or have any
2323
* questions.
2424
*/
25-
package com.oracle.svm.graal.hotspot.libgraal;
25+
package jdk.graal.compiler.hotspot.libgraal;
2626

2727
import java.io.ByteArrayInputStream;
2828
import java.io.IOException;
@@ -38,59 +38,58 @@
3838
import java.nio.file.Path;
3939
import java.security.ProtectionDomain;
4040
import java.util.ArrayList;
41-
import java.util.Collections;
4241
import java.util.Enumeration;
4342
import java.util.HashMap;
4443
import java.util.List;
4544
import java.util.Map;
4645
import java.util.NoSuchElementException;
4746
import java.util.Objects;
4847
import java.util.Set;
48+
import java.util.function.Consumer;
4949

50-
import com.oracle.svm.core.SubstrateUtil;
51-
import com.oracle.svm.core.util.VMError;
50+
import org.graalvm.nativeimage.Platform;
51+
import org.graalvm.nativeimage.Platforms;
52+
import org.graalvm.nativeimage.hosted.Feature;
5253

53-
import com.oracle.svm.util.ModuleSupport;
54+
import jdk.graal.compiler.debug.GraalError;
5455
import jdk.internal.jimage.BasicImageReader;
5556
import jdk.internal.jimage.ImageLocation;
56-
import org.graalvm.nativeimage.Platform;
57-
import org.graalvm.nativeimage.Platforms;
57+
import jdk.internal.module.Modules;
5858

5959
/**
6060
* A classloader, that reads class files and resources from a jimage file at image build time.
6161
*/
62-
public class LibGraalClassLoader extends ClassLoader {
62+
@Platforms(Platform.HOSTED_ONLY.class)
63+
final class HostedLibGraalClassLoader extends ClassLoader {
64+
65+
private static final String JAVA_HOME_PROPERTY_KEY = "jdk.graal.internal.libgraal.javahome";
66+
private static final String JAVA_HOME_PROPERTY_VALUE = System.getProperty(JAVA_HOME_PROPERTY_KEY, System.getProperty("java.home"));
6367

6468
/**
6569
* Reader for the image.
6670
*/
67-
@Platforms(Platform.HOSTED_ONLY.class) //
6871
private final BasicImageReader imageReader;
6972

7073
/**
7174
* Map from the name of a resource (without module qualifier) to its path in the image.
7275
*/
73-
@Platforms(Platform.HOSTED_ONLY.class) //
7476
private final Map<String, String> resources = new HashMap<>();
7577

7678
/**
7779
* Map from the {@linkplain Class#forName(String) name} of a class to the image path of its
7880
* class file.
7981
*/
80-
@Platforms(Platform.HOSTED_ONLY.class) //
8182
private final Map<String, String> classes = new HashMap<>();
8283

8384
/**
8485
* Map from a service name to a list of providers.
8586
*/
86-
@Platforms(Platform.HOSTED_ONLY.class) //
8787
private final Map<String, List<String>> services = new HashMap<>();
8888

8989
/**
9090
* Map from the {@linkplain Class#forName(String) name} of a class to the name of its enclosing
9191
* module.
9292
*/
93-
@Platforms(Platform.HOSTED_ONLY.class) //
9493
private final Map<String, String> modules;
9594

9695
/**
@@ -100,7 +99,6 @@ public class LibGraalClassLoader extends ClassLoader {
10099
"jdk.internal.vm.ci",
101100
"org.graalvm.collections",
102101
"org.graalvm.word",
103-
"org.graalvm.nativeimage",
104102
"jdk.graal.compiler",
105103
"org.graalvm.truffle.compiler",
106104
"com.oracle.graal.graal_enterprise");
@@ -109,17 +107,29 @@ public class LibGraalClassLoader extends ClassLoader {
109107
ClassLoader.registerAsParallelCapable();
110108
}
111109

112-
/**
113-
* @param imagePath path to the runtime image of a Java installation
114-
*/
115-
@Platforms(Platform.HOSTED_ONLY.class)
116-
LibGraalClassLoader(Path imagePath) {
117-
super("LibGraalClassLoader", null);
110+
public final Path libGraalJavaHome;
111+
112+
public HostedLibGraalClassLoader() {
113+
super(LibGraalClassLoader.LOADER_NAME, Feature.class.getClassLoader());
114+
libGraalJavaHome = Path.of(JAVA_HOME_PROPERTY_VALUE);
115+
118116
Map<String, String> modulesMap = new HashMap<>();
119117
try {
120-
// Need access to jdk.internal.jimage
121-
ModuleSupport.accessPackagesToClass(ModuleSupport.Access.EXPORT, getClass(), false,
122-
"java.base", "jdk.internal.jimage");
118+
/*
119+
* Access to jdk.internal.jimage classes is needed by this Classloader implementation.
120+
*/
121+
var javaBaseModule = Object.class.getModule();
122+
Modules.addExports(javaBaseModule, "jdk.internal.jimage", HostedLibGraalClassLoader.class.getModule());
123+
124+
/*
125+
* The classes that will get loaded by this loader require access to several internal
126+
* packages of java.base. Make sure packages will be accessible to those classes.
127+
*/
128+
Module unnamedModuleOfThisLoader = getUnnamedModule();
129+
Modules.addExports(javaBaseModule, "jdk.internal.vm", unnamedModuleOfThisLoader);
130+
Modules.addExports(javaBaseModule, "jdk.internal.misc", unnamedModuleOfThisLoader);
131+
132+
Path imagePath = libGraalJavaHome.resolve(Path.of("lib", "modules"));
123133
this.imageReader = BasicImageReader.open(imagePath);
124134
for (var entry : imageReader.getEntryNames()) {
125135
int secondSlash = entry.indexOf('/', 1);
@@ -152,15 +162,33 @@ public class LibGraalClassLoader extends ClassLoader {
152162

153163
/**
154164
* Gets an unmodifiable map from the {@linkplain Class#forName(String) name} of a class to the
155-
* name of its enclosing module.
165+
* name of its enclosing module. Reflectively accessed by
166+
* {@code LibGraalFeature.OptionCollector#afterAnalysis(AfterAnalysisAccess)}.
156167
*/
168+
@SuppressWarnings("unused")
157169
public Map<String, String> getModules() {
158170
return modules;
159171
}
160172

173+
/* 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+
}
187+
}
188+
161189
@Override
162190
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
163-
if (!SubstrateUtil.HOSTED || !classes.containsKey(name)) {
191+
if (!classes.containsKey(name)) {
164192
return super.loadClass(name, resolve);
165193
}
166194
synchronized (getClassLoadingLock(name)) {
@@ -172,40 +200,18 @@ protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundE
172200
}
173201
}
174202

175-
@Platforms(Platform.HOSTED_ONLY.class)
176-
public Class<?> loadClassOrFail(Class<?> c) {
177-
if (c.getClassLoader() == this) {
178-
return c;
179-
}
180-
if (c.isArray()) {
181-
return loadClassOrFail(c.getComponentType()).arrayType();
182-
}
183-
return loadClassOrFail(c.getName());
184-
}
185-
186-
@Platforms(Platform.HOSTED_ONLY.class)
187-
public Class<?> loadClassOrFail(String name) {
188-
try {
189-
return loadClass(name);
190-
} catch (ClassNotFoundException e) {
191-
throw VMError.shouldNotReachHere("%s unable to load class '%s'", getName(), name);
192-
}
193-
}
194-
195203
@Override
196204
protected Class<?> findClass(final String name)
197205
throws ClassNotFoundException {
198-
if (SubstrateUtil.HOSTED) {
199-
String path = name.replace('.', '/').concat(".class");
200-
201-
String pathInImage = resources.get(path);
202-
if (pathInImage != null) {
203-
ImageLocation location = imageReader.findLocation(pathInImage);
204-
if (location != null) {
205-
ByteBuffer bb = Objects.requireNonNull(imageReader.getResourceBuffer(location));
206-
ProtectionDomain pd = null;
207-
return super.defineClass(name, bb, pd);
208-
}
206+
String path = name.replace('.', '/').concat(".class");
207+
208+
String pathInImage = resources.get(path);
209+
if (pathInImage != null) {
210+
ImageLocation location = imageReader.findLocation(pathInImage);
211+
if (location != null) {
212+
ByteBuffer bb = Objects.requireNonNull(imageReader.getResourceBuffer(location));
213+
ProtectionDomain pd = null;
214+
return super.defineClass(name, bb, pd);
209215
}
210216
}
211217
throw new ClassNotFoundException(name);
@@ -222,35 +228,32 @@ protected Class<?> findClass(final String name)
222228
*/
223229
private static final String RESOURCE_PROTOCOL = "resource";
224230

225-
@Platforms(Platform.HOSTED_ONLY.class) //
226231
private URLStreamHandler serviceHandler;
227232

228233
@Override
229234
protected URL findResource(String name) {
230-
if (SubstrateUtil.HOSTED) {
231-
URLStreamHandler handler = this.serviceHandler;
232-
if (handler == null) {
233-
this.serviceHandler = handler = new ImageURLStreamHandler();
234-
}
235-
if (name.startsWith("META-INF/services/")) {
236-
String service = name.substring("META-INF/services/".length());
237-
if (services.containsKey(service)) {
238-
try {
239-
var uri = new URI(SERVICE_PROTOCOL, service, null);
240-
return URL.of(uri, handler);
241-
} catch (URISyntaxException | MalformedURLException e) {
242-
return null;
243-
}
235+
URLStreamHandler handler = this.serviceHandler;
236+
if (handler == null) {
237+
this.serviceHandler = handler = new ImageURLStreamHandler();
238+
}
239+
if (name.startsWith("META-INF/services/")) {
240+
String service = name.substring("META-INF/services/".length());
241+
if (services.containsKey(service)) {
242+
try {
243+
var uri = new URI(SERVICE_PROTOCOL, service, null);
244+
return URL.of(uri, handler);
245+
} catch (URISyntaxException | MalformedURLException e) {
246+
return null;
244247
}
245-
} else {
246-
String path = resources.get(name);
247-
if (path != null) {
248-
try {
249-
var uri = new URI(RESOURCE_PROTOCOL, name, null);
250-
return URL.of(uri, handler);
251-
} catch (URISyntaxException | MalformedURLException e) {
252-
return null;
253-
}
248+
}
249+
} else {
250+
String path = resources.get(name);
251+
if (path != null) {
252+
try {
253+
var uri = new URI(RESOURCE_PROTOCOL, name, null);
254+
return URL.of(uri, handler);
255+
} catch (URISyntaxException | MalformedURLException e) {
256+
return null;
254257
}
255258
}
256259
}
@@ -259,9 +262,6 @@ protected URL findResource(String name) {
259262

260263
@Override
261264
protected Enumeration<URL> findResources(String name) throws IOException {
262-
if (!SubstrateUtil.HOSTED) {
263-
return Collections.emptyEnumeration();
264-
}
265265
return new Enumeration<>() {
266266
private URL next = findResource(name);
267267

@@ -284,9 +284,8 @@ public URL nextElement() {
284284

285285
/**
286286
* A {@link URLStreamHandler} for use with URLs returned by
287-
* {@link LibGraalClassLoader#findResource(java.lang.String)}.
287+
* {@link HostedLibGraalClassLoader#findResource(java.lang.String)}.
288288
*/
289-
@Platforms(Platform.HOSTED_ONLY.class)
290289
private class ImageURLStreamHandler extends URLStreamHandler {
291290
@Override
292291
public URLConnection openConnection(URL u) {
@@ -307,7 +306,6 @@ public URLConnection openConnection(URL u) {
307306
}
308307
}
309308

310-
@Platforms(Platform.HOSTED_ONLY.class)
311309
private static class ImageURLConnection extends URLConnection {
312310
private final byte[] bytes;
313311
private InputStream in;
@@ -341,4 +339,23 @@ public String getContentType() {
341339
return "application/octet-stream";
342340
}
343341
}
342+
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() {
349+
return LibGraalClassLoader.singleton;
350+
}
351+
}
352+
353+
public final class LibGraalClassLoader extends ClassLoader {
354+
355+
static final String LOADER_NAME = "LibGraalClassLoader";
356+
static final LibGraalClassLoader singleton = new LibGraalClassLoader();
357+
358+
private LibGraalClassLoader() {
359+
super(LOADER_NAME, null);
360+
}
344361
}

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotReplacementsImpl.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,6 @@
6464
import jdk.vm.ci.meta.MetaAccessProvider;
6565
import jdk.vm.ci.meta.ResolvedJavaMethod;
6666
import jdk.vm.ci.meta.ResolvedJavaType;
67-
import org.graalvm.nativeimage.Platform;
68-
import org.graalvm.nativeimage.Platforms;
6967

7068
/**
7169
* Filters certain method substitutions based on whether there is underlying hardware support for
@@ -276,7 +274,6 @@ public <T> T getInjectedArgument(Class<T> capability) {
276274
return super.getInjectedArgument(capability);
277275
}
278276

279-
@Platforms(Platform.HOSTED_ONLY.class)
280277
public ResolvedJavaMethod findSnippetMethod(ResolvedJavaMethod thisMethod) {
281278
if (snippetEncoder == null) {
282279
throw new GraalError("findSnippetMethod called before initialization of Replacements");

substratevm/mx.substratevm/mx_substratevm.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1468,6 +1468,7 @@ def _native_image_launcher_extra_jvm_args():
14681468
libgraal_jar_distributions = [
14691469
'sdk:NATIVEBRIDGE',
14701470
'sdk:JNIUTILS',
1471+
'compiler:LIBGRAAL_LOADER',
14711472
'substratevm:LIBGRAAL_LIBRARY']
14721473

14731474
def allow_build_path_in_libgraal():

substratevm/mx.substratevm/suite.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1386,7 +1386,6 @@
13861386
],
13871387
"requiresConcealed" : {
13881388
"java.base" : [
1389-
"jdk.internal.jimage",
13901389
"jdk.internal.misc",
13911390
],
13921391
"jdk.internal.vm.ci" : [

0 commit comments

Comments
 (0)