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
2727import java .io .ByteArrayInputStream ;
2828import java .io .IOException ;
3838import java .nio .file .Path ;
3939import java .security .ProtectionDomain ;
4040import java .util .ArrayList ;
41- import java .util .Collections ;
4241import java .util .Enumeration ;
4342import java .util .HashMap ;
4443import java .util .List ;
4544import java .util .Map ;
4645import java .util .NoSuchElementException ;
4746import java .util .Objects ;
4847import 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 ;
5455import jdk .internal .jimage .BasicImageReader ;
5556import 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 = "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}
0 commit comments