< prev index next >

src/java.base/share/classes/java/lang/ClassLoader.java

Print this page




  22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  23  * or visit www.oracle.com if you need additional information or have any
  24  * questions.
  25  */
  26 
  27 package java.lang;
  28 
  29 import java.io.InputStream;
  30 import java.io.IOException;
  31 import java.io.UncheckedIOException;
  32 import java.io.File;
  33 import java.lang.reflect.Constructor;
  34 import java.lang.reflect.InvocationTargetException;
  35 import java.net.URL;
  36 import java.security.AccessController;
  37 import java.security.AccessControlContext;
  38 import java.security.CodeSource;
  39 import java.security.PrivilegedAction;
  40 import java.security.ProtectionDomain;
  41 import java.security.cert.Certificate;
  42 import java.util.ArrayDeque;
  43 import java.util.ArrayList;
  44 import java.util.Arrays;
  45 import java.util.Collections;
  46 import java.util.Deque;
  47 import java.util.Enumeration;
  48 import java.util.HashMap;
  49 import java.util.HashSet;
  50 import java.util.Map;
  51 import java.util.NoSuchElementException;
  52 import java.util.Objects;
  53 import java.util.Set;
  54 import java.util.Spliterator;
  55 import java.util.Spliterators;
  56 import java.util.WeakHashMap;
  57 import java.util.concurrent.ConcurrentHashMap;
  58 import java.util.function.Supplier;
  59 import java.util.stream.Stream;
  60 import java.util.stream.StreamSupport;
  61 
  62 import jdk.internal.loader.BuiltinClassLoader;
  63 import jdk.internal.perf.PerfCounter;
  64 import jdk.internal.loader.BootLoader;

  65 import jdk.internal.loader.ClassLoaders;



  66 import jdk.internal.misc.Unsafe;
  67 import jdk.internal.misc.VM;
  68 import jdk.internal.ref.CleanerFactory;
  69 import jdk.internal.reflect.CallerSensitive;
  70 import jdk.internal.reflect.Reflection;
  71 import jdk.internal.util.StaticProperty;
  72 import sun.reflect.misc.ReflectUtil;
  73 import sun.security.util.SecurityConstants;
  74 
  75 /**
  76  * A class loader is an object that is responsible for loading classes. The
  77  * class {@code ClassLoader} is an abstract class.  Given the <a
  78  * href="#binary-name">binary name</a> of a class, a class loader should attempt to
  79  * locate or generate data that constitutes a definition for the class.  A
  80  * typical strategy is to transform the name into a file name and then read a
  81  * "class file" of that name from a file system.
  82  *
  83  * <p> Every {@link java.lang.Class Class} object contains a {@link
  84  * Class#getClassLoader() reference} to the {@code ClassLoader} that defined
  85  * it.
  86  *
  87  * <p> {@code Class} objects for array classes are not created by class
  88  * loaders, but are created automatically as required by the Java runtime.


2360      * Returns the absolute path name of a native library.  The VM invokes this
2361      * method to locate the native libraries that belong to classes loaded with
2362      * this class loader. If this method returns {@code null}, the VM
2363      * searches the library along the path specified as the
2364      * "{@code java.library.path}" property.
2365      *
2366      * @param  libname
2367      *         The library name
2368      *
2369      * @return  The absolute path of the native library
2370      *
2371      * @see  System#loadLibrary(String)
2372      * @see  System#mapLibraryName(String)
2373      *
2374      * @since  1.2
2375      */
2376     protected String findLibrary(String libname) {
2377         return null;
2378     }
2379 
2380     /**
2381      * The inner class NativeLibrary denotes a loaded native library instance.
2382      * Every classloader contains a vector of loaded native libraries in the
2383      * private field {@code nativeLibraries}.  The native libraries loaded
2384      * into the system are entered into the {@code systemNativeLibraries}
2385      * vector.
2386      *
2387      * <p> Every native library requires a particular version of JNI. This is
2388      * denoted by the private {@code jniVersion} field.  This field is set by
2389      * the VM when it loads the library, and used by the VM to pass the correct
2390      * version of JNI to the native methods.  </p>
2391      *
2392      * @see      ClassLoader
2393      * @since    1.2
2394      */
2395     static class NativeLibrary {
2396         // the class from which the library is loaded, also indicates
2397         // the loader this native library belongs.
2398         final Class<?> fromClass;
2399         // the canonicalized name of the native library.
2400         // or static library name
2401         final String name;
2402         // Indicates if the native library is linked into the VM
2403         final boolean isBuiltin;
2404 
2405         // opaque handle to native library, used in native code.
2406         long handle;
2407         // the version of JNI environment the native library requires.
2408         int jniVersion;
2409 
2410         native boolean load0(String name, boolean isBuiltin);
2411 
2412         native long findEntry(String name);
2413 
2414         NativeLibrary(Class<?> fromClass, String name, boolean isBuiltin) {
2415             this.name = name;
2416             this.fromClass = fromClass;
2417             this.isBuiltin = isBuiltin;
2418         }
2419 
2420         /*
2421          * Loads the native library and registers for cleanup when its
2422          * associated class loader is unloaded
2423          */
2424         boolean load() {
2425             if (handle != 0) {
2426                 throw new InternalError("Native library " + name + " has been loaded");
2427             }
2428 
2429             if (!load0(name, isBuiltin)) return false;
2430 
2431             // register the class loader for cleanup when unloaded
2432             // builtin class loaders are never unloaded
2433             ClassLoader loader = fromClass.getClassLoader();
2434             if (loader != null &&
2435                 loader != getBuiltinPlatformClassLoader() &&
2436                 loader != getBuiltinAppClassLoader()) {
2437                 CleanerFactory.cleaner().register(loader,
2438                         new Unloader(name, handle, isBuiltin));
2439             }
2440             return true;
2441         }
2442 
2443         static boolean loadLibrary(Class<?> fromClass, String name, boolean isBuiltin) {
2444             ClassLoader loader =
2445                 fromClass == null ? null : fromClass.getClassLoader();
2446 
2447             synchronized (loadedLibraryNames) {
2448                 Map<String, NativeLibrary> libs =
2449                     loader != null ? loader.nativeLibraries() : systemNativeLibraries();
2450                 if (libs.containsKey(name)) {
2451                     return true;
2452                 }
2453 
2454                 if (loadedLibraryNames.contains(name)) {
2455                     throw new UnsatisfiedLinkError("Native Library " + name +
2456                         " already loaded in another classloader");
2457                 }
2458 
2459                 /*
2460                  * When a library is being loaded, JNI_OnLoad function can cause
2461                  * another loadLibrary invocation that should succeed.
2462                  *
2463                  * We use a static stack to hold the list of libraries we are
2464                  * loading because this can happen only when called by the
2465                  * same thread because this block is synchronous.
2466                  *
2467                  * If there is a pending load operation for the library, we
2468                  * immediately return success; otherwise, we raise
2469                  * UnsatisfiedLinkError.
2470                  */
2471                 for (NativeLibrary lib : nativeLibraryContext) {
2472                     if (name.equals(lib.name)) {
2473                         if (loader == lib.fromClass.getClassLoader()) {
2474                             return true;
2475                         } else {
2476                             throw new UnsatisfiedLinkError("Native Library " +
2477                                 name + " is being loaded in another classloader");
2478                         }
2479                     }
2480                 }
2481                 NativeLibrary lib = new NativeLibrary(fromClass, name, isBuiltin);
2482                 // load the native library
2483                 nativeLibraryContext.push(lib);
2484                 try {
2485                     if (!lib.load()) return false;
2486                 } finally {
2487                     nativeLibraryContext.pop();
2488                 }
2489                 // register the loaded native library
2490                 loadedLibraryNames.add(name);
2491                 libs.put(name, lib);
2492             }
2493             return true;
2494         }
2495 
2496         // Invoked in the VM to determine the context class in JNI_OnLoad
2497         // and JNI_OnUnload
2498         static Class<?> getFromClass() {
2499             return nativeLibraryContext.peek().fromClass;
2500         }
2501 
2502         // native libraries being loaded
2503         static Deque<NativeLibrary> nativeLibraryContext = new ArrayDeque<>(8);
2504 
2505         /*
2506          * The run() method will be invoked when this class loader becomes
2507          * phantom reachable to unload the native library.
2508          */
2509         static class Unloader implements Runnable {
2510             // This represents the context when a native library is unloaded
2511             // and getFromClass() will return null,
2512             static final NativeLibrary UNLOADER =
2513                 new NativeLibrary(null, "dummy", false);
2514             final String name;
2515             final long handle;
2516             final boolean isBuiltin;
2517 
2518             Unloader(String name, long handle, boolean isBuiltin) {
2519                 if (handle == 0) {
2520                     throw new IllegalArgumentException(
2521                         "Invalid handle for native library " + name);
2522                 }
2523 
2524                 this.name = name;
2525                 this.handle = handle;
2526                 this.isBuiltin = isBuiltin;
2527             }
2528 
2529             @Override
2530             public void run() {
2531                 synchronized (loadedLibraryNames) {
2532                     /* remove the native library name */
2533                     loadedLibraryNames.remove(name);
2534                     nativeLibraryContext.push(UNLOADER);
2535                     try {
2536                         unload(name, isBuiltin, handle);
2537                     } finally {
2538                         nativeLibraryContext.pop();
2539                     }
2540 
2541                 }
2542             }
2543         }
2544 
2545         // JNI FindClass expects the caller class if invoked from JNI_OnLoad
2546         // and JNI_OnUnload is NativeLibrary class
2547         static native void unload(String name, boolean isBuiltin, long handle);
2548     }
2549 
2550     /**
2551      * Holds system and user library paths derived from the
2552      * {@code java.library.path} and {@code sun.boot.library.path} system
2553      * properties. The system properties are eagerly read at bootstrap, then
2554      * lazily parsed on first use to avoid initialization ordering issues.
2555      */
2556     private static class LibraryPaths {
2557         static final String[] USER =
2558                 ClassLoaderHelper.parsePath(StaticProperty.javaLibraryPath());
2559         static final String[] SYS =
2560                 ClassLoaderHelper.parsePath(StaticProperty.sunBootLibraryPath());
2561     }
2562 
2563     // Invoked in the java.lang.Runtime class to implement load and loadLibrary.
2564     static void loadLibrary(Class<?> fromClass, String name,
2565                             boolean isAbsolute) {
2566         ClassLoader loader =
2567             (fromClass == null) ? null : fromClass.getClassLoader();
2568 
2569         if (isAbsolute) {
2570             if (loadLibrary0(fromClass, new File(name))) {
2571                 return;







2572             }
2573             throw new UnsatisfiedLinkError("Can't load library: " + name);

2574         }
2575         if (loader != null) {


2576             String libfilename = loader.findLibrary(name);
2577             if (libfilename != null) {
2578                 File libfile = new File(libfilename);
2579                 if (!libfile.isAbsolute()) {
2580                     throw new UnsatisfiedLinkError(
2581                         "ClassLoader.findLibrary failed to return an absolute path: " + libfilename);
2582                 }
2583                 if (loadLibrary0(fromClass, libfile)) {
2584                     return;

2585                 }
2586                 throw new UnsatisfiedLinkError("Can't load " + libfilename);
2587             }




2588         }
2589         for (String sysPath : LibraryPaths.SYS) {
2590             File libfile = new File(sysPath, System.mapLibraryName(name));
2591             if (loadLibrary0(fromClass, libfile)) {
2592                 return;
2593             }
2594             libfile = ClassLoaderHelper.mapAlternativeName(libfile);
2595             if (libfile != null && loadLibrary0(fromClass, libfile)) {
2596                 return;
2597             }
2598         }
2599         if (loader != null) {
2600             for (String userPath : LibraryPaths.USER) {
2601                 File libfile = new File(userPath, System.mapLibraryName(name));
2602                 if (loadLibrary0(fromClass, libfile)) {
2603                     return;
2604                 }
2605                 libfile = ClassLoaderHelper.mapAlternativeName(libfile);
2606                 if (libfile != null && loadLibrary0(fromClass, libfile)) {
2607                     return;
2608                 }
2609             }
2610         }
2611         // Oops, it failed
2612         throw new UnsatisfiedLinkError("no " + name +
2613             " in java.library.path: " + Arrays.toString(LibraryPaths.USER));
2614     }
2615 
2616     private static native String findBuiltinLib(String name);
2617 
2618     private static boolean loadLibrary0(Class<?> fromClass, final File file) {
2619         // Check to see if we're attempting to access a static library
2620         String name = findBuiltinLib(file.getName());
2621         boolean isBuiltin = (name != null);
2622         if (!isBuiltin) {
2623             name = AccessController.doPrivileged(
2624                 new PrivilegedAction<>() {
2625                     public String run() {
2626                         try {
2627                             return file.exists() ? file.getCanonicalPath() : null;
2628                         } catch (IOException e) {
2629                             return null;
2630                         }
2631                     }
2632                 });
2633             if (name == null) {
2634                 return false;
2635             }
2636         }
2637         return NativeLibrary.loadLibrary(fromClass, name, isBuiltin);
2638     }
2639 
2640     /*
2641      * Invoked in the VM class linking code.
2642      */
2643     private static long findNative(ClassLoader loader, String entryName) {
2644         Map<String, NativeLibrary> libs =
2645             loader != null ? loader.nativeLibraries() : systemNativeLibraries();
2646         if (libs.isEmpty())
2647             return 0;
2648 
2649         // the native libraries map may be updated in another thread
2650         // when a native library is being loaded.  No symbol will be
2651         // searched from it yet.
2652         for (NativeLibrary lib : libs.values()) {
2653             long entry = lib.findEntry(entryName);
2654             if (entry != 0) return entry;
2655         }
2656         return 0;
2657     }
2658 
2659     // All native library names we've loaded.
2660     // This also serves as the lock to obtain nativeLibraries
2661     // and write to nativeLibraryContext.
2662     private static final Set<String> loadedLibraryNames = new HashSet<>();
2663 
2664     // Native libraries belonging to system classes.
2665     private static volatile Map<String, NativeLibrary> systemNativeLibraries;
2666 
2667     // Native libraries associated with the class loader.
2668     private volatile Map<String, NativeLibrary> nativeLibraries;
2669 
2670     /*
2671      * Returns the native libraries map associated with bootstrap class loader
2672      * This method will create the map at the first time when called.
2673      */
2674     private static Map<String, NativeLibrary> systemNativeLibraries() {
2675         Map<String, NativeLibrary> libs = systemNativeLibraries;
2676         if (libs == null) {
2677             synchronized (loadedLibraryNames) {
2678                 libs = systemNativeLibraries;
2679                 if (libs == null) {
2680                     libs = systemNativeLibraries = new ConcurrentHashMap<>();
2681                 }
2682             }
2683         }
2684         return libs;
2685     }
2686 
2687     /*
2688      * Returns the native libraries map associated with this class loader
2689      * This method will create the map at the first time when called.
2690      */
2691     private Map<String, NativeLibrary> nativeLibraries() {
2692         Map<String, NativeLibrary> libs = nativeLibraries;
2693         if (libs == null) {
2694             synchronized (loadedLibraryNames) {
2695                 libs = nativeLibraries;
2696                 if (libs == null) {
2697                     libs = nativeLibraries = new ConcurrentHashMap<>();
2698                 }
2699             }
2700         }
2701         return libs;
2702     }
2703 
2704     // -- Assertion management --
2705 
2706     final Object assertionLock;
2707 
2708     // The default toggle for assertion checking.
2709     // @GuardedBy("assertionLock")
2710     private boolean defaultAssertionStatus = false;
2711 
2712     // Maps String packageName to Boolean package default assertion status Note
2713     // that the default package is placed under a null map key.  If this field
2714     // is null then we are delegating assertion status queries to the VM, i.e.,
2715     // none of this ClassLoader's assertion status modification methods have
2716     // been invoked.
2717     // @GuardedBy("assertionLock")
2718     private Map<String, Boolean> packageAssertionStatus = null;
2719 
2720     // Maps String fullyQualifiedClassName to Boolean assertionStatus If this
2721     // field is null then we are delegating assertion status queries to the VM,




  22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  23  * or visit www.oracle.com if you need additional information or have any
  24  * questions.
  25  */
  26 
  27 package java.lang;
  28 
  29 import java.io.InputStream;
  30 import java.io.IOException;
  31 import java.io.UncheckedIOException;
  32 import java.io.File;
  33 import java.lang.reflect.Constructor;
  34 import java.lang.reflect.InvocationTargetException;
  35 import java.net.URL;
  36 import java.security.AccessController;
  37 import java.security.AccessControlContext;
  38 import java.security.CodeSource;
  39 import java.security.PrivilegedAction;
  40 import java.security.ProtectionDomain;
  41 import java.security.cert.Certificate;

  42 import java.util.ArrayList;

  43 import java.util.Collections;

  44 import java.util.Enumeration;
  45 import java.util.HashMap;
  46 import java.util.HashSet;
  47 import java.util.Map;
  48 import java.util.NoSuchElementException;
  49 import java.util.Objects;
  50 import java.util.Set;
  51 import java.util.Spliterator;
  52 import java.util.Spliterators;
  53 import java.util.WeakHashMap;
  54 import java.util.concurrent.ConcurrentHashMap;
  55 import java.util.function.Supplier;
  56 import java.util.stream.Stream;
  57 import java.util.stream.StreamSupport;
  58 


  59 import jdk.internal.loader.BootLoader;
  60 import jdk.internal.loader.BuiltinClassLoader;
  61 import jdk.internal.loader.ClassLoaders;
  62 import jdk.internal.loader.NativeLibrary;
  63 import jdk.internal.loader.NativeLibraries;
  64 import jdk.internal.perf.PerfCounter;
  65 import jdk.internal.misc.Unsafe;
  66 import jdk.internal.misc.VM;

  67 import jdk.internal.reflect.CallerSensitive;
  68 import jdk.internal.reflect.Reflection;
  69 import jdk.internal.util.StaticProperty;
  70 import sun.reflect.misc.ReflectUtil;
  71 import sun.security.util.SecurityConstants;
  72 
  73 /**
  74  * A class loader is an object that is responsible for loading classes. The
  75  * class {@code ClassLoader} is an abstract class.  Given the <a
  76  * href="#binary-name">binary name</a> of a class, a class loader should attempt to
  77  * locate or generate data that constitutes a definition for the class.  A
  78  * typical strategy is to transform the name into a file name and then read a
  79  * "class file" of that name from a file system.
  80  *
  81  * <p> Every {@link java.lang.Class Class} object contains a {@link
  82  * Class#getClassLoader() reference} to the {@code ClassLoader} that defined
  83  * it.
  84  *
  85  * <p> {@code Class} objects for array classes are not created by class
  86  * loaders, but are created automatically as required by the Java runtime.


2358      * Returns the absolute path name of a native library.  The VM invokes this
2359      * method to locate the native libraries that belong to classes loaded with
2360      * this class loader. If this method returns {@code null}, the VM
2361      * searches the library along the path specified as the
2362      * "{@code java.library.path}" property.
2363      *
2364      * @param  libname
2365      *         The library name
2366      *
2367      * @return  The absolute path of the native library
2368      *
2369      * @see  System#loadLibrary(String)
2370      * @see  System#mapLibraryName(String)
2371      *
2372      * @since  1.2
2373      */
2374     protected String findLibrary(String libname) {
2375         return null;
2376     }
2377 
2378     private final NativeLibraries libraries = new NativeLibraries(this);





















































































































































































2379 
2380     // Invoked in the java.lang.Runtime class to implement load and loadLibrary.
2381     static NativeLibrary loadLibrary(Class<?> fromClass, File file) {
2382         ClassLoader loader = (fromClass == null) ? null : fromClass.getClassLoader();
2383         NativeLibraries libs = loader != null ? loader.libraries : BootLoader.getNativeLibraries();
2384         NativeLibrary nl = libs.loadLibrary(fromClass, file);
2385         if (nl != null) {
2386             return nl;
2387         }
2388         throw new UnsatisfiedLinkError("Can't load library: " + file);
2389     }
2390     static NativeLibrary loadLibrary(Class<?> fromClass, String name) {
2391         ClassLoader loader = (fromClass == null) ? null : fromClass.getClassLoader();
2392         if (loader == null) {
2393             NativeLibrary nl = BootLoader.getNativeLibraries().loadLibrary(fromClass, name);
2394             if (nl != null) {
2395                 return nl;
2396             }
2397             throw new UnsatisfiedLinkError("no " + name +
2398                     " in system library path: " + StaticProperty.sunBootLibraryPath());
2399         }
2400 
2401         NativeLibraries libs = loader.libraries;
2402         // First load from the file returned from ClassLoader::findLibrary, if found.
2403         String libfilename = loader.findLibrary(name);
2404         if (libfilename != null) {
2405             File libfile = new File(libfilename);
2406             if (!libfile.isAbsolute()) {
2407                 throw new UnsatisfiedLinkError(
2408                         "ClassLoader.findLibrary failed to return an absolute path: " + libfilename);
2409             }
2410             NativeLibrary nl = libs.loadLibrary(fromClass, libfile);
2411             if (nl != null) {
2412                 return nl;
2413             }
2414             throw new UnsatisfiedLinkError("Can't load " + libfilename);
2415         }
2416         // Then load from system library path and java library path
2417         NativeLibrary nl = libs.loadLibrary(fromClass, name);
2418         if (nl != null) {
2419             return nl;
2420         }
2421 





















2422         // Oops, it failed
2423         throw new UnsatisfiedLinkError("no " + name +
2424                 " in java.library.path: " + StaticProperty.javaLibraryPath());
























2425     }
2426 
2427     /*
2428      * Invoked in the VM class linking code.
2429      */
2430     private static long findNative(ClassLoader loader, String entryName) {
2431         if (loader == null) {
2432             return BootLoader.getNativeLibraries().lookup(entryName);
2433         } else {
2434             return loader.libraries.lookup(entryName);




















































2435         }

2436     }
2437 
2438     // -- Assertion management --
2439 
2440     final Object assertionLock;
2441 
2442     // The default toggle for assertion checking.
2443     // @GuardedBy("assertionLock")
2444     private boolean defaultAssertionStatus = false;
2445 
2446     // Maps String packageName to Boolean package default assertion status Note
2447     // that the default package is placed under a null map key.  If this field
2448     // is null then we are delegating assertion status queries to the VM, i.e.,
2449     // none of this ClassLoader's assertion status modification methods have
2450     // been invoked.
2451     // @GuardedBy("assertionLock")
2452     private Map<String, Boolean> packageAssertionStatus = null;
2453 
2454     // Maps String fullyQualifiedClassName to Boolean assertionStatus If this
2455     // field is null then we are delegating assertion status queries to the VM,


< prev index next >