Path: blob/master/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java
41159 views
/*1* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package jdk.internal.loader;2627import java.io.IOException;28import java.net.URL;29import java.nio.file.InvalidPathException;30import java.nio.file.Path;31import java.security.CodeSource;32import java.security.PermissionCollection;33import java.util.jar.Manifest;3435import jdk.internal.access.JavaLangAccess;36import jdk.internal.access.SharedSecrets;37import jdk.internal.misc.VM;38import jdk.internal.module.ServicesCatalog;3940/**41* Creates and provides access to the built-in platform and application class42* loaders. It also creates the class loader that is used to locate resources43* in modules defined to the boot class loader.44*/4546public class ClassLoaders {4748private ClassLoaders() { }4950private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();5152// the built-in class loaders53private static final BootClassLoader BOOT_LOADER;54private static final PlatformClassLoader PLATFORM_LOADER;55private static final AppClassLoader APP_LOADER;5657// Sets the ServicesCatalog for the specified loader using archived objects.58private static void setArchivedServicesCatalog(ClassLoader loader) {59ServicesCatalog catalog = ArchivedClassLoaders.get().servicesCatalog(loader);60ServicesCatalog.putServicesCatalog(loader, catalog);61}6263// Creates the built-in class loaders.64static {65ArchivedClassLoaders archivedClassLoaders = ArchivedClassLoaders.get();66if (archivedClassLoaders != null) {67// assert VM.getSavedProperty("jdk.boot.class.path.append") == null68BOOT_LOADER = (BootClassLoader) archivedClassLoaders.bootLoader();69setArchivedServicesCatalog(BOOT_LOADER);70PLATFORM_LOADER = (PlatformClassLoader) archivedClassLoaders.platformLoader();71setArchivedServicesCatalog(PLATFORM_LOADER);72} else {73// -Xbootclasspath/a or -javaagent with Boot-Class-Path attribute74String append = VM.getSavedProperty("jdk.boot.class.path.append");75URLClassPath ucp = (append != null && !append.isEmpty())76? new URLClassPath(append, true)77: null;78BOOT_LOADER = new BootClassLoader(ucp);79PLATFORM_LOADER = new PlatformClassLoader(BOOT_LOADER);80}81// A class path is required when no initial module is specified.82// In this case the class path defaults to "", meaning the current83// working directory. When an initial module is specified, on the84// contrary, we drop this historic interpretation of the empty85// string and instead treat it as unspecified.86String cp = System.getProperty("java.class.path");87if (cp == null || cp.isEmpty()) {88String initialModuleName = System.getProperty("jdk.module.main");89cp = (initialModuleName == null) ? "" : null;90}91URLClassPath ucp = new URLClassPath(cp, false);92if (archivedClassLoaders != null) {93APP_LOADER = (AppClassLoader) archivedClassLoaders.appLoader();94setArchivedServicesCatalog(APP_LOADER);95APP_LOADER.setClassPath(ucp);96} else {97APP_LOADER = new AppClassLoader(PLATFORM_LOADER, ucp);98ArchivedClassLoaders.archive();99}100}101102/**103* Returns the class loader that is used to find resources in modules104* defined to the boot class loader.105*106* @apiNote This method is not public, it should instead be used via107* the BootLoader class that provides a restricted API to this class108* loader.109*/110static BuiltinClassLoader bootLoader() {111return BOOT_LOADER;112}113114/**115* Returns the platform class loader.116*/117public static ClassLoader platformClassLoader() {118return PLATFORM_LOADER;119}120121/**122* Returns the application class loader.123*/124public static ClassLoader appClassLoader() {125return APP_LOADER;126}127128/**129* The class loader that is used to find resources in modules defined to130* the boot class loader. It is not used for class loading.131*/132private static class BootClassLoader extends BuiltinClassLoader {133BootClassLoader(URLClassPath bcp) {134super(null, null, bcp);135}136137@Override138protected Class<?> loadClassOrNull(String cn, boolean resolve) {139return JLA.findBootstrapClassOrNull(cn);140}141};142143/**144* The platform class loader, a unique type to make it easier to distinguish145* from the application class loader.146*/147private static class PlatformClassLoader extends BuiltinClassLoader {148static {149if (!ClassLoader.registerAsParallelCapable())150throw new InternalError();151}152153PlatformClassLoader(BootClassLoader parent) {154super("platform", parent, null);155}156}157158/**159* The application class loader that is a {@code BuiltinClassLoader} with160* customizations to be compatible with long standing behavior.161*/162private static class AppClassLoader extends BuiltinClassLoader {163static {164if (!ClassLoader.registerAsParallelCapable())165throw new InternalError();166}167168AppClassLoader(BuiltinClassLoader parent, URLClassPath ucp) {169super("app", parent, ucp);170}171172@Override173protected Class<?> loadClass(String cn, boolean resolve)174throws ClassNotFoundException175{176// for compatibility reasons, say where restricted package list has177// been updated to list API packages in the unnamed module.178@SuppressWarnings("removal")179SecurityManager sm = System.getSecurityManager();180if (sm != null) {181int i = cn.lastIndexOf('.');182if (i != -1) {183sm.checkPackageAccess(cn.substring(0, i));184}185}186187return super.loadClass(cn, resolve);188}189190@Override191protected PermissionCollection getPermissions(CodeSource cs) {192PermissionCollection perms = super.getPermissions(cs);193perms.add(new RuntimePermission("exitVM"));194return perms;195}196197/**198* Called by the VM to support dynamic additions to the class path199*200* @see java.lang.instrument.Instrumentation#appendToSystemClassLoaderSearch201*/202void appendToClassPathForInstrumentation(String path) {203appendClassPath(path);204}205206/**207* Called by the VM to support define package for AppCDS208*/209protected Package defineOrCheckPackage(String pn, Manifest man, URL url) {210return super.defineOrCheckPackage(pn, man, url);211}212213/**214* Called by the VM, during -Xshare:dump215*/216private void resetArchivedStates() {217setClassPath(null);218}219}220221/**222* Attempts to convert the given string to a file URL.223*224* @apiNote This is called by the VM225*/226@Deprecated227private static URL toFileURL(String s) {228try {229// Use an intermediate File object to construct a URI/URL without230// authority component as URLClassPath can't handle URLs with a UNC231// server name in the authority component.232return Path.of(s).toRealPath().toFile().toURI().toURL();233} catch (InvalidPathException | IOException ignore) {234// malformed path string or class path element does not exist235return null;236}237}238}239240241