|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
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; |
|
} |
|
} |
|
} |