22
22
* or visit www.oracle.com if you need additional information or have any
23
23
* questions.
24
24
*/
25
- package com . oracle . svm . graal .hotspot .libgraal ;
25
+ package jdk . graal . compiler .hotspot .libgraal ;
26
26
27
27
import java .io .ByteArrayInputStream ;
28
28
import java .io .IOException ;
38
38
import java .nio .file .Path ;
39
39
import java .security .ProtectionDomain ;
40
40
import java .util .ArrayList ;
41
- import java .util .Collections ;
42
41
import java .util .Enumeration ;
43
42
import java .util .HashMap ;
44
43
import java .util .List ;
45
44
import java .util .Map ;
46
45
import java .util .NoSuchElementException ;
47
46
import java .util .Objects ;
48
47
import java .util .Set ;
48
+ import java .util .function .Consumer ;
49
49
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 ;
52
53
53
- import com . oracle . svm . util . ModuleSupport ;
54
+ import jdk . graal . compiler . debug . GraalError ;
54
55
import jdk .internal .jimage .BasicImageReader ;
55
56
import jdk .internal .jimage .ImageLocation ;
56
- import org .graalvm .nativeimage .Platform ;
57
- import org .graalvm .nativeimage .Platforms ;
57
+ import jdk .internal .module .Modules ;
58
58
59
59
/**
60
60
* A classloader, that reads class files and resources from a jimage file at image build time.
61
61
*/
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" ));
63
67
64
68
/**
65
69
* Reader for the image.
66
70
*/
67
- @ Platforms (Platform .HOSTED_ONLY .class ) //
68
71
private final BasicImageReader imageReader ;
69
72
70
73
/**
71
74
* Map from the name of a resource (without module qualifier) to its path in the image.
72
75
*/
73
- @ Platforms (Platform .HOSTED_ONLY .class ) //
74
76
private final Map <String , String > resources = new HashMap <>();
75
77
76
78
/**
77
79
* Map from the {@linkplain Class#forName(String) name} of a class to the image path of its
78
80
* class file.
79
81
*/
80
- @ Platforms (Platform .HOSTED_ONLY .class ) //
81
82
private final Map <String , String > classes = new HashMap <>();
82
83
83
84
/**
84
85
* Map from a service name to a list of providers.
85
86
*/
86
- @ Platforms (Platform .HOSTED_ONLY .class ) //
87
87
private final Map <String , List <String >> services = new HashMap <>();
88
88
89
89
/**
90
90
* Map from the {@linkplain Class#forName(String) name} of a class to the name of its enclosing
91
91
* module.
92
92
*/
93
- @ Platforms (Platform .HOSTED_ONLY .class ) //
94
93
private final Map <String , String > modules ;
95
94
96
95
/**
@@ -100,7 +99,6 @@ public class LibGraalClassLoader extends ClassLoader {
100
99
"jdk.internal.vm.ci" ,
101
100
"org.graalvm.collections" ,
102
101
"org.graalvm.word" ,
103
- "org.graalvm.nativeimage" ,
104
102
"jdk.graal.compiler" ,
105
103
"org.graalvm.truffle.compiler" ,
106
104
"com.oracle.graal.graal_enterprise" );
@@ -109,17 +107,29 @@ public class LibGraalClassLoader extends ClassLoader {
109
107
ClassLoader .registerAsParallelCapable ();
110
108
}
111
109
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
+
118
116
Map <String , String > modulesMap = new HashMap <>();
119
117
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" ));
123
133
this .imageReader = BasicImageReader .open (imagePath );
124
134
for (var entry : imageReader .getEntryNames ()) {
125
135
int secondSlash = entry .indexOf ('/' , 1 );
@@ -152,15 +162,33 @@ public class LibGraalClassLoader extends ClassLoader {
152
162
153
163
/**
154
164
* 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)}.
156
167
*/
168
+ @ SuppressWarnings ("unused" )
157
169
public Map <String , String > getModules () {
158
170
return modules ;
159
171
}
160
172
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
+
161
189
@ Override
162
190
protected Class <?> loadClass (String name , boolean resolve ) throws ClassNotFoundException {
163
- if (!SubstrateUtil . HOSTED || ! classes .containsKey (name )) {
191
+ if (!classes .containsKey (name )) {
164
192
return super .loadClass (name , resolve );
165
193
}
166
194
synchronized (getClassLoadingLock (name )) {
@@ -172,40 +200,18 @@ protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundE
172
200
}
173
201
}
174
202
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
-
195
203
@ Override
196
204
protected Class <?> findClass (final String name )
197
205
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 );
209
215
}
210
216
}
211
217
throw new ClassNotFoundException (name );
@@ -222,35 +228,32 @@ protected Class<?> findClass(final String name)
222
228
*/
223
229
private static final String RESOURCE_PROTOCOL = "resource" ;
224
230
225
- @ Platforms (Platform .HOSTED_ONLY .class ) //
226
231
private URLStreamHandler serviceHandler ;
227
232
228
233
@ Override
229
234
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 ;
244
247
}
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 ;
254
257
}
255
258
}
256
259
}
@@ -259,9 +262,6 @@ protected URL findResource(String name) {
259
262
260
263
@ Override
261
264
protected Enumeration <URL > findResources (String name ) throws IOException {
262
- if (!SubstrateUtil .HOSTED ) {
263
- return Collections .emptyEnumeration ();
264
- }
265
265
return new Enumeration <>() {
266
266
private URL next = findResource (name );
267
267
@@ -284,9 +284,8 @@ public URL nextElement() {
284
284
285
285
/**
286
286
* A {@link URLStreamHandler} for use with URLs returned by
287
- * {@link LibGraalClassLoader #findResource(java.lang.String)}.
287
+ * {@link HostedLibGraalClassLoader #findResource(java.lang.String)}.
288
288
*/
289
- @ Platforms (Platform .HOSTED_ONLY .class )
290
289
private class ImageURLStreamHandler extends URLStreamHandler {
291
290
@ Override
292
291
public URLConnection openConnection (URL u ) {
@@ -307,7 +306,6 @@ public URLConnection openConnection(URL u) {
307
306
}
308
307
}
309
308
310
- @ Platforms (Platform .HOSTED_ONLY .class )
311
309
private static class ImageURLConnection extends URLConnection {
312
310
private final byte [] bytes ;
313
311
private InputStream in ;
@@ -341,4 +339,23 @@ public String getContentType() {
341
339
return "application/octet-stream" ;
342
340
}
343
341
}
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
+ }
344
361
}
0 commit comments