25
25
package com .oracle .svm .hosted ;
26
26
27
27
import java .io .IOException ;
28
+ import java .lang .reflect .Constructor ;
28
29
import java .lang .reflect .Method ;
29
30
import java .net .URL ;
30
31
import java .security .SecureClassLoader ;
31
32
import java .util .Collections ;
32
33
import java .util .Enumeration ;
34
+ import java .util .List ;
33
35
import java .util .Set ;
34
36
import java .util .WeakHashMap ;
35
37
import java .util .jar .JarFile ;
@@ -135,34 +137,55 @@ public boolean isDisallowedClassLoader(ClassLoader c) {
135
137
private static final Method defineClass = ReflectionUtil .lookupMethod (ClassLoader .class , "defineClass" ,
136
138
String .class , byte [].class , int .class , int .class );
137
139
138
- static Class <?> loadClass (ClassLoader classLoader , String name , boolean resolve ) throws ClassNotFoundException {
139
- Class <?> loadedClass = null ;
140
+ private static final Constructor <Enumeration <?>> compoundEnumerationConstructor ;
141
+ static {
142
+ /* Reuse utility class defined as package-private class in java.lang.ClassLoader.java */
143
+ String className = "java.lang.CompoundEnumeration" ;
140
144
try {
141
- /* invoke the "loadClass" method on the current class loader */
142
- loadedClass = ((Class <?>) loadClass .invoke (classLoader , name , resolve ));
143
- } catch (Exception e ) {
144
- if (e .getCause () instanceof ClassNotFoundException ) {
145
- throw ((ClassNotFoundException ) e .getCause ());
145
+ @ SuppressWarnings ("unchecked" )
146
+ Class <Enumeration <?>> compoundEnumerationClass = (Class <Enumeration <?>>) Class .forName (className );
147
+ compoundEnumerationConstructor = ReflectionUtil .lookupConstructor (compoundEnumerationClass , Enumeration [].class );
148
+ } catch (ClassNotFoundException | ReflectionUtil .ReflectionUtilError e ) {
149
+ throw VMError .shouldNotReachHere ("Unable to get access to class " + className , e );
150
+ }
151
+ }
152
+
153
+ private static Class <?> loadClass (List <ClassLoader > activeClassLoaders , String name , boolean resolve ) throws ClassNotFoundException {
154
+ ClassNotFoundException classNotFoundException = null ;
155
+ for (ClassLoader loader : activeClassLoaders ) {
156
+ try {
157
+ /* invoke the "loadClass" method on the current class loader */
158
+ return ((Class <?>) loadClass .invoke (loader , name , resolve ));
159
+ } catch (Exception e ) {
160
+ if (e .getCause () instanceof ClassNotFoundException ) {
161
+ classNotFoundException = ((ClassNotFoundException ) e .getCause ());
162
+ } else {
163
+ String message = String .format ("Can not load class: %s, with class loader: %s" , name , loader );
164
+ VMError .shouldNotReachHere (message , e );
165
+ }
146
166
}
147
- String message = String .format ("Can not load class: %s, with class loader: %s" , name , classLoader );
148
- VMError .shouldNotReachHere (message , e );
149
167
}
150
- return loadedClass ;
168
+ VMError .guarantee (classNotFoundException != null );
169
+ throw classNotFoundException ;
151
170
}
152
171
153
- static URL findResource (ClassLoader classLoader , String name ) {
154
- try {
155
- // invoke the "findResource" method on the current class loader
156
- return (URL ) findResource .invoke (classLoader , name );
157
- } catch (ReflectiveOperationException e ) {
158
- String message = String .format ("Can not find resource: %s using class loader: %s" , name , classLoader );
159
- VMError .shouldNotReachHere (message , e );
172
+ private static URL findResource (List <ClassLoader > activeClassLoaders , String name ) {
173
+ for (ClassLoader loader : activeClassLoaders ) {
174
+ try {
175
+ // invoke the "findResource" method on the current class loader
176
+ Object url = findResource .invoke (loader , name );
177
+ if (url != null )
178
+ return (URL ) url ;
179
+ } catch (ReflectiveOperationException | ClassCastException e ) {
180
+ String message = String .format ("Can not find resource: %s using class loader: %s" , name , loader );
181
+ VMError .shouldNotReachHere (message , e );
182
+ }
160
183
}
161
184
return null ;
162
185
}
163
186
164
187
@ SuppressWarnings ("unchecked" )
165
- static Enumeration <URL > findResources (ClassLoader classLoader , String name ) {
188
+ private static Enumeration <URL > findResources (ClassLoader classLoader , String name ) {
166
189
try {
167
190
// invoke the "findResources" method on the current class loader
168
191
return (Enumeration <URL >) findResources .invoke (classLoader , name );
@@ -186,22 +209,38 @@ static Class<?> defineClass(ClassLoader classLoader, String name, byte[] b, int
186
209
187
210
@ Override
188
211
protected Class <?> loadClass (String name , boolean resolve ) throws ClassNotFoundException {
189
- return loadClass (getActiveClassLoader (), name , resolve );
212
+ return loadClass (getActiveClassLoaders (), name , resolve );
190
213
}
191
214
192
215
@ Override
193
216
protected URL findResource (String name ) {
194
- return findResource (getActiveClassLoader (), name );
217
+ return findResource (getActiveClassLoaders (), name );
195
218
}
196
219
197
220
@ Override
198
221
protected Enumeration <URL > findResources (String name ) throws IOException {
199
- return findResources (getActiveClassLoader (), name );
222
+ List <ClassLoader > activeClassLoaders = getActiveClassLoaders ();
223
+ assert !activeClassLoaders .isEmpty () & activeClassLoaders .size () <= 2 ;
224
+ ClassLoader activeClassLoader = activeClassLoaders .get (0 );
225
+ ClassLoader activeClassLoaderParent = activeClassLoaders .size () > 1 ? activeClassLoaders .get (1 ) : null ;
226
+ if (activeClassLoaderParent != null ) {
227
+ return newCompoundEnumeration (findResources (activeClassLoaderParent , name ), findResources (activeClassLoader , name ));
228
+ }
229
+ return findResources (activeClassLoader , name );
230
+ }
231
+
232
+ @ SuppressWarnings ("unchecked" )
233
+ private static <T > Enumeration <T > newCompoundEnumeration (Enumeration <?>... enums ) {
234
+ try {
235
+ return (Enumeration <T >) compoundEnumerationConstructor .newInstance ((Object ) enums );
236
+ } catch (ReflectiveOperationException e ) {
237
+ throw VMError .shouldNotReachHere ("Cannot instantiate CompoundEnumeration" , e );
238
+ }
200
239
}
201
240
202
241
public Class <?> forNameOrNull (String name , boolean initialize ) {
203
242
try {
204
- return Class .forName (name , initialize , getActiveClassLoader ( ));
243
+ return Class .forName (name , initialize , getActiveClassLoaders (). get ( 0 ));
205
244
} catch (LinkageError | ClassNotFoundException ignored ) {
206
245
return null ;
207
246
}
@@ -212,7 +251,7 @@ public Class<?> predefineClass(String name, byte[] array, int offset, int length
212
251
if (forNameOrNull (name , false ) != null ) {
213
252
throw VMError .shouldNotReachHere ("The class loader hierarchy already provides a class with the same name as the class submitted for predefinition: " + name );
214
253
}
215
- return defineClass (getActiveClassLoader ( ), name , array , offset , length );
254
+ return defineClass (getActiveClassLoaders (). get ( 0 ), name , array , offset , length );
216
255
}
217
256
218
257
@ Override
@@ -224,11 +263,18 @@ public String toString() {
224
263
'}' ;
225
264
}
226
265
227
- private ClassLoader getActiveClassLoader () {
228
- ClassLoader delegate = nativeImageClassLoader ;
229
- return delegate != null
230
- ? delegate
231
- : defaultSystemClassLoader ;
266
+ private List <ClassLoader > getActiveClassLoaders () {
267
+ ClassLoader activeClassLoader = nativeImageClassLoader ;
268
+ if (activeClassLoader != null ) {
269
+ ClassLoader activeClassLoaderParent = activeClassLoader .getParent ();
270
+ if (activeClassLoaderParent instanceof NativeImageClassLoaderSupport .ClassPathClassLoader ) {
271
+ return List .of (activeClassLoader , activeClassLoaderParent );
272
+ } else {
273
+ return List .of (activeClassLoader );
274
+ }
275
+ } else {
276
+ return List .of (defaultSystemClassLoader );
277
+ }
232
278
}
233
279
234
280
/**
0 commit comments