| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package jdk.internal.loader;  | 
 | 
 | 
 | 
import java.io.IOException;  | 
 | 
import java.net.URL;  | 
 | 
import java.nio.file.InvalidPathException;  | 
 | 
import java.nio.file.Path;  | 
 | 
import java.security.CodeSource;  | 
 | 
import java.security.PermissionCollection;  | 
 | 
import java.util.jar.Manifest;  | 
 | 
 | 
 | 
import jdk.internal.access.JavaLangAccess;  | 
 | 
import jdk.internal.access.SharedSecrets;  | 
 | 
import jdk.internal.misc.VM;  | 
 | 
import jdk.internal.module.ServicesCatalog;  | 
 | 
 | 
 | 
/**  | 
 | 
 * Creates and provides access to the built-in platform and application class  | 
 | 
 * loaders. It also creates the class loader that is used to locate resources  | 
 | 
 * in modules defined to the boot class loader.  | 
 | 
 */  | 
 | 
 | 
 | 
public class ClassLoaders { | 
 | 
 | 
 | 
    private ClassLoaders() { } | 
 | 
 | 
 | 
    private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();  | 
 | 
 | 
 | 
      | 
 | 
    private static final BootClassLoader BOOT_LOADER;  | 
 | 
    private static final PlatformClassLoader PLATFORM_LOADER;  | 
 | 
    private static final AppClassLoader APP_LOADER;  | 
 | 
 | 
 | 
      | 
 | 
    private static void setArchivedServicesCatalog(ClassLoader loader) { | 
 | 
        ServicesCatalog catalog = ArchivedClassLoaders.get().servicesCatalog(loader);  | 
 | 
        ServicesCatalog.putServicesCatalog(loader, catalog);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    static { | 
 | 
        ArchivedClassLoaders archivedClassLoaders = ArchivedClassLoaders.get();  | 
 | 
        if (archivedClassLoaders != null) { | 
 | 
              | 
 | 
            BOOT_LOADER = (BootClassLoader) archivedClassLoaders.bootLoader();  | 
 | 
            setArchivedServicesCatalog(BOOT_LOADER);  | 
 | 
            PLATFORM_LOADER = (PlatformClassLoader) archivedClassLoaders.platformLoader();  | 
 | 
            setArchivedServicesCatalog(PLATFORM_LOADER);  | 
 | 
        } else { | 
 | 
              | 
 | 
            String append = VM.getSavedProperty("jdk.boot.class.path.append"); | 
 | 
            URLClassPath ucp = (append != null && !append.isEmpty())  | 
 | 
                    ? new URLClassPath(append, true)  | 
 | 
                    : null;  | 
 | 
            BOOT_LOADER = new BootClassLoader(ucp);  | 
 | 
            PLATFORM_LOADER = new PlatformClassLoader(BOOT_LOADER);  | 
 | 
        }  | 
 | 
        // A class path is required when no initial module is specified.  | 
 | 
        // In this case the class path defaults to "", meaning the current  | 
 | 
        // working directory.  When an initial module is specified, on the  | 
 | 
        // contrary, we drop this historic interpretation of the empty  | 
 | 
          | 
 | 
        String cp = System.getProperty("java.class.path"); | 
 | 
        if (cp == null || cp.isEmpty()) { | 
 | 
            String initialModuleName = System.getProperty("jdk.module.main"); | 
 | 
            cp = (initialModuleName == null) ? "" : null;  | 
 | 
        }  | 
 | 
        URLClassPath ucp = new URLClassPath(cp, false);  | 
 | 
        if (archivedClassLoaders != null) { | 
 | 
            APP_LOADER = (AppClassLoader) archivedClassLoaders.appLoader();  | 
 | 
            setArchivedServicesCatalog(APP_LOADER);  | 
 | 
            APP_LOADER.setClassPath(ucp);  | 
 | 
        } else { | 
 | 
            APP_LOADER = new AppClassLoader(PLATFORM_LOADER, ucp);  | 
 | 
            ArchivedClassLoaders.archive();  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    static BuiltinClassLoader bootLoader() { | 
 | 
        return BOOT_LOADER;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public static ClassLoader platformClassLoader() { | 
 | 
        return PLATFORM_LOADER;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public static ClassLoader appClassLoader() { | 
 | 
        return APP_LOADER;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static class BootClassLoader extends BuiltinClassLoader { | 
 | 
        BootClassLoader(URLClassPath bcp) { | 
 | 
            super(null, null, bcp);  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        protected Class<?> loadClassOrNull(String cn, boolean resolve) { | 
 | 
            return JLA.findBootstrapClassOrNull(cn);  | 
 | 
        }  | 
 | 
    };  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static class PlatformClassLoader extends BuiltinClassLoader { | 
 | 
        static { | 
 | 
            if (!ClassLoader.registerAsParallelCapable())  | 
 | 
                throw new InternalError();  | 
 | 
        }  | 
 | 
 | 
 | 
        PlatformClassLoader(BootClassLoader parent) { | 
 | 
            super("platform", parent, null); | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static class AppClassLoader extends BuiltinClassLoader { | 
 | 
        static { | 
 | 
            if (!ClassLoader.registerAsParallelCapable())  | 
 | 
                throw new InternalError();  | 
 | 
        }  | 
 | 
 | 
 | 
        AppClassLoader(BuiltinClassLoader parent, URLClassPath ucp) { | 
 | 
            super("app", parent, ucp); | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        protected Class<?> loadClass(String cn, boolean resolve)  | 
 | 
            throws ClassNotFoundException  | 
 | 
        { | 
 | 
            // for compatibility reasons, say where restricted package list has  | 
 | 
              | 
 | 
            @SuppressWarnings("removal") | 
 | 
            SecurityManager sm = System.getSecurityManager();  | 
 | 
            if (sm != null) { | 
 | 
                int i = cn.lastIndexOf('.'); | 
 | 
                if (i != -1) { | 
 | 
                    sm.checkPackageAccess(cn.substring(0, i));  | 
 | 
                }  | 
 | 
            }  | 
 | 
 | 
 | 
            return super.loadClass(cn, resolve);  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        protected PermissionCollection getPermissions(CodeSource cs) { | 
 | 
            PermissionCollection perms = super.getPermissions(cs);  | 
 | 
            perms.add(new RuntimePermission("exitVM")); | 
 | 
            return perms;  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
         */  | 
 | 
        void appendToClassPathForInstrumentation(String path) { | 
 | 
            appendClassPath(path);  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
         */  | 
 | 
        protected Package defineOrCheckPackage(String pn, Manifest man, URL url) { | 
 | 
            return super.defineOrCheckPackage(pn, man, url);  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
         */  | 
 | 
        private void resetArchivedStates() { | 
 | 
            setClassPath(null);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    @Deprecated  | 
 | 
    private static URL toFileURL(String s) { | 
 | 
        try { | 
 | 
            // Use an intermediate File object to construct a URI/URL without  | 
 | 
            // authority component as URLClassPath can't handle URLs with a UNC  | 
 | 
              | 
 | 
            return Path.of(s).toRealPath().toFile().toURI().toURL();  | 
 | 
        } catch (InvalidPathException | IOException ignore) { | 
 | 
              | 
 | 
            return null;  | 
 | 
        }  | 
 | 
    }  | 
 | 
}  |