/* * Copyright (C) 2014 The Android Open Source Project * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, Azul Systems, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package java.lang; import java.io.InputStream; import java.io.IOException; import java.io.UncheckedIOException; import java.io.File; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.net.URL; import java.security.AccessController; import java.security.AccessControlContext; import java.security.CodeSource; import java.security.PrivilegedAction; import java.security.ProtectionDomain; import java.security.cert.Certificate; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Set; import java.util.Spliterator; import java.util.Spliterators; import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Supplier; import java.util.stream.Stream; import java.util.stream.StreamSupport; import dalvik.system.PathClassLoader; import jdk.internal.misc.Unsafe; import jdk.internal.misc.VM; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; import jdk.internal.util.StaticProperty; import sun.reflect.misc.ReflectUtil; import sun.security.util.SecurityConstants; // Android-changed: Removed javadoc related to getPlatformClassLoader(). /** * A class loader is an object that is responsible for loading classes. The * class {@code ClassLoader} is an abstract class. Given the binary name of a class, a class loader should attempt to * locate or generate data that constitutes a definition for the class. A * typical strategy is to transform the name into a file name and then read a * "class file" of that name from a file system. * *
Every {@link java.lang.Class Class} object contains a {@link * Class#getClassLoader() reference} to the {@code ClassLoader} that defined * it. * *
{@code Class} objects for array classes are not created by class * loaders, but are created automatically as required by the Java runtime. * The class loader for an array class, as returned by {@link * Class#getClassLoader()} is the same as the class loader for its element * type; if the element type is a primitive type, then the array class has no * class loader. * *
Applications implement subclasses of {@code ClassLoader} in order to * extend the manner in which the Java virtual machine dynamically loads * classes. * *
Class loaders may typically be used by security managers to indicate * security domains. * *
In addition to loading classes, a class loader is also responsible for * locating resources. A resource is some data (a "{@code .class}" file, * configuration data, or an image for example) that is identified with an * abstract '/'-separated path name. Resources are typically packaged with an * application or library so that they can be located by code in the * application or library. In some cases, the resources are included so that * they can be located by other libraries. * *
The {@code ClassLoader} class uses a delegation model to search for * classes and resources. Each instance of {@code ClassLoader} has an * associated parent class loader. When requested to find a class or * resource, a {@code ClassLoader} instance will usually delegate the search * for the class or resource to its parent class loader before attempting to * find the class or resource itself. * *
Class loaders that support concurrent loading of classes are known as * {@code #isRegisteredAsParallelCapable() parallel capable} class * loaders and are required to register themselves at their class initialization * time by invoking the {@code * #registerAsParallelCapable ClassLoader.registerAsParallelCapable} * method. Note that the {@code ClassLoader} class is registered as parallel * capable by default. However, its subclasses still need to register themselves * if they are parallel capable. * In environments in which the delegation model is not strictly * hierarchical, class loaders need to be parallel capable, otherwise class * loading can lead to deadlocks because the loader lock is held for the * duration of the class loading process (see {@link #loadClass * loadClass} methods). * *
Bootstrap class loader. * It is the virtual machine's built-in class loader, typically represented * as {@code null}, and does not have a parent.
{@linkplain #getSystemClassLoader() System class loader}. * It is also known as application class loader and is distinct * from the platform class loader. * The system class loader is typically used to define classes on the * application class path, module path, and JDK-specific tools. * The platform class loader is the parent or an ancestor of the system class * loader, so the system class loader can load platform classes by delegating * to its parent.
Normally, the Java virtual machine loads classes from the local file * system in a platform-dependent manner. * However, some classes may not originate from a file; they may originate * from other sources, such as the network, or they could be constructed by an * application. The method {@link #defineClass(String, byte[], int, int) * defineClass} converts an array of bytes into an instance of class * {@code Class}. Instances of this newly defined class can be created using * {@link Class#newInstance Class.newInstance}. * *
The methods and constructors of objects created by a class loader may * reference other classes. To determine the class(es) referred to, the Java * virtual machine invokes the {@link #loadClass loadClass} method of * the class loader that originally created the class. * *
For example, an application could create a network class loader to * download class files from a server. Sample code might look like: * *
* ** ClassLoader loader = new NetworkClassLoader(host, port); * Object main = loader.loadClass("Main", true).newInstance(); * . . . *
The network class loader subclass must define the methods {@link * #findClass findClass} and {@code loadClassData} to load a class * from the network. Once it has downloaded the bytes that make up the class, * it should use the method {@link #defineClass defineClass} to * create a class instance. A sample implementation is: * *
* ** class NetworkClassLoader extends ClassLoader { * String host; * int port; * * public Class findClass(String name) { * byte[] b = loadClassData(name); * return defineClass(name, b, 0, b.length); * } * * private byte[] loadClassData(String name) { * // load the class data from the connection * . . . * } * } *
Any class name provided as a {@code String} parameter to methods in * {@code ClassLoader} must be a binary name as defined by * The Java Language Specification. * *
Examples of valid class names include: *
* ** "java.lang.String" * "javax.swing.JSpinner$DefaultEditor" * "java.security.KeyStore$Builder$FileBuilder$1" * "java.net.URLClassLoader$3$1" *
Any package name provided as a {@code String} parameter to methods in
* {@code ClassLoader} must be either the empty string (denoting an unnamed package)
* or a fully qualified name as defined by
* The Java Language Specification.
*
* @jls 6.7 Fully Qualified Names
* @jls 13.1 The Form of a Binary
* @see #resolveClass(Class)
* @since 1.0
* @revised 9
*/
public abstract class ClassLoader {
static private class SystemClassLoader {
public static ClassLoader loader = ClassLoader.createSystemClassLoader();
}
// Android-removed: Removed the unused field.
/**
* To avoid unloading individual classes, {@link java.lang.reflect.Proxy}
* only generates one class for each set of interfaces. This maps sets of
* interfaces to the proxy class that implements all of them. It is declared
* here so that these generated classes can be unloaded with their class
* loader.
*
* @hide
*/
public final Map If there is a security manager, its {@link
* SecurityManager#checkCreateClassLoader() checkCreateClassLoader} method
* is invoked. This may result in a security exception. If there is a security manager, its {@link
* SecurityManager#checkCreateClassLoader()
* checkCreateClassLoader} method is invoked. This may result in
* a security exception. Unless overridden, this method synchronizes on the result of
// {@link #getClassLoadingLock getClassLoadingLock} method
// during the entire class loading process.
/**
* Loads the class with the specified binary name. The
* default implementation of this method searches for classes in the
* following order:
*
* Invoke {@link #findLoadedClass(String)} to check if the class
* has already been loaded. Invoke the {@link #loadClass(String) loadClass} method
* on the parent class loader. If the parent is {@code null} the class
* loader built into the virtual machine is used, instead. Invoke the {@link #findClass(String)} method to find the
* class. If the class was found using the above steps, and the
* {@code resolve} flag is true, this method will then invoke the {@link
* #resolveClass(Class)} method on the resulting {@code Class} object.
*
* Subclasses of {@code ClassLoader} are encouraged to override {@link
* #findClass(String)}, rather than this method. This method assigns a default {@link java.security.ProtectionDomain
* ProtectionDomain} to the newly defined class. The
* {@code ProtectionDomain} is effectively granted the same set of
* permissions returned when {@link
* java.security.Policy#getPermissions(java.security.CodeSource)
* Policy.getPolicy().getPermissions(new CodeSource(null, null))}
* is invoked. The default protection domain is created on the first invocation
* of {@link #defineClass(String, byte[], int, int) defineClass},
* and re-used on subsequent invocations.
*
* To assign a specific {@code ProtectionDomain} to the class, use
* the {@link #defineClass(String, byte[], int, int,
* java.security.ProtectionDomain) defineClass} method that takes a
* {@code ProtectionDomain} as one of its arguments.
* This method defines a package in this class loader corresponding to the
* package of the {@code Class} (if such a package has not already been defined
* in this class loader). The name of the defined package is derived from
* the binary name of the class specified by
* the byte array {@code b}.
* Other properties of the defined package are as specified by {@link Package}.
*
* @param name
* The expected binary name of the class, or
* {@code null} if not known
*
* @param b
* The bytes that make up the class data. The bytes in positions
* {@code off} through {@code off+len-1} should have the format
* of a valid class file as defined by
* The Java Virtual Machine Specification.
*
* @param off
* The start offset in {@code b} of the class data
*
* @param len
* The length of the class data
*
* @return The {@code Class} object that was created from the specified
* class data.
*
* @throws ClassFormatError
* If the data did not contain a valid class
*
* @throws IndexOutOfBoundsException
* If either {@code off} or {@code len} is negative, or if
* {@code off+len} is greater than {@code b.length}.
*
* @throws SecurityException
* If an attempt is made to add this class to a package that
* contains classes that were signed by a different set of
* certificates than this class (which is unsigned), or if
* {@code name} begins with "{@code java.}".
*
* @see #loadClass(String, boolean)
* @see #resolveClass(Class)
* @see java.security.CodeSource
* @see java.security.SecureClassLoader
*
* @since 1.1
* @revised 9
*/
protected final Class> defineClass(String name, byte[] b, int off, int len)
throws ClassFormatError
{
throw new UnsupportedOperationException("can't load this type of class file");
}
/**
* Converts an array of bytes into an instance of class {@code Class},
* with a given {@code ProtectionDomain}.
*
* If the given {@code ProtectionDomain} is {@code null},
* then a default protection domain will be assigned to the class as specified
* in the documentation for {@link #defineClass(String, byte[], int, int)}.
* Before the class can be used it must be resolved.
*
* The first class defined in a package determines the exact set of
* certificates that all subsequent classes defined in that package must
* contain. The set of certificates for a class is obtained from the
* {@link java.security.CodeSource CodeSource} within the
* {@code ProtectionDomain} of the class. Any classes added to that
* package must contain the same set of certificates or a
* {@code SecurityException} will be thrown. Note that if
* {@code name} is {@code null}, this check is not performed.
* You should always pass in the binary name of the
* class you are defining as well as the bytes. This ensures that the
* class you are defining is indeed the class you think it is.
*
* This method defines a package in this class loader corresponding to the
* package of the {@code Class} (if such a package has not already been defined
* in this class loader). The name of the defined package is derived from
* the binary name of the class specified by
* the byte array {@code b}.
* Other properties of the defined package are as specified by {@link Package}.
*
* @param name
* The expected binary name of the class, or
* {@code null} if not known
*
* @param b
* The bytes that make up the class data. The bytes in positions
* {@code off} through {@code off+len-1} should have the format
* of a valid class file as defined by
* The Java Virtual Machine Specification.
*
* @param off
* The start offset in {@code b} of the class data
*
* @param len
* The length of the class data
*
* @param protectionDomain
* The {@code ProtectionDomain} of the class
*
* @return The {@code Class} object created from the data,
* and {@code ProtectionDomain}.
*
* @throws ClassFormatError
* If the data did not contain a valid class
*
* @throws NoClassDefFoundError
* If {@code name} is not {@code null} and not equal to the
* binary name of the class specified by {@code b}
*
* @throws IndexOutOfBoundsException
* If either {@code off} or {@code len} is negative, or if
* {@code off+len} is greater than {@code b.length}.
*
* @throws SecurityException
* If an attempt is made to add this class to a package that
* contains classes that were signed by a different set of
* certificates than this class, or if {@code name} begins with
* "{@code java.}" and this class loader is not the platform
* class loader or its ancestor.
*
* @revised 9
*/
// Android-changed: Remove from link for NoClassDefFoundError
// Android-changed: Removed javadoc related to the getPlatformClassLoader().
protected final Class> defineClass(String name, byte[] b, int off, int len,
ProtectionDomain protectionDomain)
throws ClassFormatError
{
// Android-changed: Android doesn't support loading .class file.
// protectionDomain = preDefineClass(name, protectionDomain);
// String source = defineClassSourceLocation(protectionDomain);
// Class> c = defineClass1(this, name, b, off, len, protectionDomain, source);
// postDefineClass(c, protectionDomain);
// return c;
throw new UnsupportedOperationException("can't load this type of class file");
}
/**
* Converts a {@link java.nio.ByteBuffer ByteBuffer} into an instance
* of class {@code Class}, with the given {@code ProtectionDomain}.
* If the given {@code ProtectionDomain} is {@code null}, then a default
* protection domain will be assigned to the class as
* specified in the documentation for {@link #defineClass(String, byte[],
* int, int)}. Before the class can be used it must be resolved.
*
* The rules about the first class defined in a package determining the
* set of certificates for the package, the restrictions on class names,
* and the defined package of the class
* are identical to those specified in the documentation for {@link
* #defineClass(String, byte[], int, int, ProtectionDomain)}.
*
* An invocation of this method of the form
* cl{@code .defineClass(}name{@code ,}
* bBuffer{@code ,} pd{@code )} yields exactly the same
* result as the statements
*
* This method loads the class through the system class loader (see
* {@link #getSystemClassLoader()}). The {@code Class} object returned
* might have more than one {@code ClassLoader} associated with it.
* Subclasses of {@code ClassLoader} need not usually invoke this method,
* because most class loaders need to override just {@link
* #findClass(String)}. The name of a resource is a '{@code /}'-separated path name thatf
* identifies the resource. The name of a resource is a {@code /}-separated path name that
* identifies the resource. The name of a resource is a {@code /}-separated path name that
* identifies the resource.
*
* The resources will be located when the returned stream is evaluated.
* If the evaluation results in an {@code IOException} then the I/O
* exception is wrapped in an {@link UncheckedIOException} that is then
* thrown.
* @implSpec The default implementation invokes {@link #getResources(String)
* getResources} to find all the resources with the given name and returns
* a stream with the elements in the enumeration as the source.
*
* @apiNote When overriding this method it is recommended that an
* implementation ensures that any delegation is consistent with the {@link
* #getResource(java.lang.String) getResource(String)} method. This should
* ensure that the first element returned by the stream is the same
* resource that the {@code getResource(String)} method would return.
*
* @param name
* The resource name
*
* @return A stream of resource {@link java.net.URL URL} objects. If no
* resources could be found, the stream will be empty. Resources
* for which a {@code URL} cannot be constructed, are in a package
* that is not opened unconditionally, or access to the resource
* is denied by the security manager, will not be in the stream.
*
* @throws NullPointerException If {@code name} is {@code null}
*
* @since 9
* @hide
*/
public Stream Note that once a class loader is registered as parallel capable, there
* is no way to change it back. The search order is described in the documentation for {@link
* #getSystemResource(String)}. The search order is described in the documentation for {@link
* #getResource(String)}. This method is first invoked early in the runtime's startup
* sequence, at which point it creates the system class loader. This
* class loader will be the context class loader for the main application
* thread (for example, the thread that invokes the {@code main} method of
* the main class).
*
* The default system class loader is an implementation-dependent
* instance of this class.
*
* @implNote The system property to override the system class loader is not
* examined until the VM is almost fully initialized. Code that executes
* this method during startup should take care not to cache the return
* value until the system is fully initialized.
*
* The name of the built-in system class loader is {@code "app"}.
* The system property "{@code java.class.path}" is read during early
* initialization of the VM to determine the class path.
* An empty value of "{@code java.class.path}" property is interpreted
* differently depending on whether the initial module (the module
* containing the main class) is named or unnamed:
* If named, the built-in system class loader will have no class path and
* will search for classes and resources using the application module path;
* otherwise, if unnamed, it will set the class path to the current
* working directory.
*
* JAR files on the class path may contain a {@code Class-Path} manifest
* attribute to specify dependent JAR files to be included in the class path.
* {@code Class-Path} entries must meet certain conditions for validity (see
* the
* JAR File Specification for details). Invalid {@code Class-Path}
* entries are ignored.
*
* @return The system {@code ClassLoader}
*
* @throws SecurityException
* If a security manager is present, and the caller's class loader
* is not {@code null} and is not the same as or an ancestor of the
* system class loader, and the caller does not have the
* {@link RuntimePermission}{@code ("getClassLoader")}
*
* @throws IllegalStateException
* If invoked recursively during the construction of the class
* loader specified by the "{@code java.system.class.loader}"
* property.
*
* @throws Error
* If the system property "{@code java.system.class.loader}"
* is defined but the named class could not be loaded, the
* provider class does not define the required constructor, or an
* exception is thrown by that constructor when it is invoked. The
* underlying cause of the error can be retrieved via the
* {@link Throwable#getCause()} method.
*
* @revised 1.4
* @revised 9
*/
@CallerSensitive
public static ClassLoader getSystemClassLoader() {
/*
switch (VM.initLevel()) {
case 0:
case 1:
case 2:
// the system class loader is the built-in app class loader during startup
return getBuiltinAppClassLoader();
case 3:
String msg = "getSystemClassLoader cannot be called during the system class loader instantiation";
throw new IllegalStateException(msg);
default:
// system fully initialized
assert VM.isBooted() && scl != null;
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkClassLoaderPermission(scl, Reflection.getCallerClass());
}
return scl;
}
*/
return SystemClassLoader.loader;
}
// Android-removed: Remove unused methods.
/*
static ClassLoader getBuiltinPlatformClassLoader() {
return ClassLoaders.platformClassLoader();
}
static ClassLoader getBuiltinAppClassLoader() {
return ClassLoaders.appClassLoader();
}
/*
* Initialize the system class loader that may be a custom class on the
* application class path or application module path.
*
* @see java.lang.System#initPhase3
*//*
static synchronized ClassLoader initSystemClassLoader() {
if (VM.initLevel() != 3) {
throw new InternalError("system class loader cannot be set at initLevel " +
VM.initLevel());
}
// detect recursive initialization
if (scl != null) {
throw new IllegalStateException("recursive invocation");
}
ClassLoader builtinLoader = getBuiltinAppClassLoader();
// All are privileged frames. No need to call doPrivileged.
String cn = System.getProperty("java.system.class.loader");
if (cn != null) {
try {
// custom class loader is only supported to be loaded from unnamed module
Constructor> ctor = Class.forName(cn, false, builtinLoader)
.getDeclaredConstructor(ClassLoader.class);
scl = (ClassLoader) ctor.newInstance(builtinLoader);
} catch (Exception e) {
Throwable cause = e;
if (e instanceof InvocationTargetException) {
cause = e.getCause();
if (cause instanceof Error) {
throw (Error) cause;
}
}
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
}
throw new Error(cause.getMessage(), cause);
}
} else {
scl = builtinLoader;
}
return scl;
}
*/
// Returns true if the specified class loader can be found in this class
// loader's delegation chain.
boolean isAncestor(ClassLoader cl) {
ClassLoader acl = this;
do {
acl = acl.parent;
if (cl == acl) {
return true;
}
} while (acl != null);
return false;
}
// Tests if class loader access requires "getClassLoader" permission
// check. A class loader 'from' can access class loader 'to' if
// class loader 'from' is same as class loader 'to' or an ancestor
// of 'to'. The class loader in a system domain can access
// any class loader.
private static boolean needsClassLoaderPermissionCheck(ClassLoader from,
ClassLoader to)
{
if (from == to)
return false;
if (from == null)
return false;
return !to.isAncestor(from);
}
// Returns the class's class loader, or null if none.
static ClassLoader getClassLoader(Class> caller) {
// This can be null if the VM is requesting it
if (caller == null) {
return null;
}
// Android-changed: Use Class.getClassLoader(); there is no Class.getClassLoader0().
// // Circumvent security check since this is package-private
// return caller.getClassLoader0();
return caller.getClassLoader();
}
// Android-removed: SecurityManager isn't supported.
/*
* Checks RuntimePermission("getClassLoader") permission
* if caller's class loader is not null and caller's class loader
* is not the same as or an ancestor of the given cl argument.
*//*
static void checkClassLoaderPermission(ClassLoader cl, Class> caller) {
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
// caller can be null if the VM is requesting it
ClassLoader ccl = getClassLoader(caller);
if (needsClassLoaderPermissionCheck(ccl, cl)) {
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
}
}
*/
// Android-removed: Remove unused scl static field.
// The system class loader
// @GuardedBy("ClassLoader.class")
// private static volatile ClassLoader scl;
// -- Package --
// Android-removed: The module system isn't supported yet.
/*
/**
* Define a Package of the given Class object.
*
* If the given class represents an array type, a primitive type or void,
* this method returns {@code null}.
*
* This method does not throw IllegalArgumentException.
*//*
Package definePackage(Class> c) {
if (c.isPrimitive() || c.isArray()) {
return null;
}
return definePackage(c.getPackageName(), c.getModule());
}
/**
* Defines a Package of the given name and module
*
* This method does not throw IllegalArgumentException.
*
* @param name package name
* @param m module
*//*
Package definePackage(String name, Module m) {
if (name.isEmpty() && m.isNamed()) {
throw new InternalError("unnamed package in " + m);
}
// check if Package object is already defined
NamedPackage pkg = packages.get(name);
if (pkg instanceof Package)
return (Package)pkg;
return (Package)packages.compute(name, (n, p) -> toPackage(n, p, m));
}
/*
* Returns a Package object for the named package
*//*
private Package toPackage(String name, NamedPackage p, Module m) {
// define Package object if the named package is not yet defined
if (p == null)
return NamedPackage.toPackage(name, m);
// otherwise, replace the NamedPackage object with Package object
if (p instanceof Package)
return (Package)p;
return NamedPackage.toPackage(p.packageName(), p.module());
}
*/
/**
* Defines a package by name in this {@code ClassLoader}.
*
* Package names must be unique within a class loader and
* cannot be redefined or changed once created.
*
* If a class loader wishes to define a package with specific properties,
* such as version information, then the class loader should call this
* {@code definePackage} method before calling {@code defineClass}.
* Otherwise, the
* {@link #defineClass(String, byte[], int, int, ProtectionDomain) defineClass}
* method will define a package in this class loader corresponding to the package
* of the newly defined class; the properties of this defined package are
* specified by {@link Package}.
*
* @apiNote
* A class loader that wishes to define a package for classes in a JAR
* typically uses the specification and implementation titles, versions, and
* vendors from the JAR's manifest. If the package is specified as
* {@linkplain java.util.jar.Attributes.Name#SEALED sealed} in the JAR's manifest,
* the {@code URL} of the JAR file is typically used as the {@code sealBase}.
* If classes of package {@code 'p'} defined by this class loader
* are loaded from multiple JARs, the {@code Package} object may contain
* different information depending on the first class of package {@code 'p'}
* defined and which JAR's manifest is read first to explicitly define
* package {@code 'p'}.
*
* It is strongly recommended that a class loader does not call this
* method to explicitly define packages in named modules; instead,
* the package will be automatically defined when a class is {@linkplain
* #defineClass(String, byte[], int, int, ProtectionDomain) being defined}.
* If it is desirable to define {@code Package} explicitly, it should ensure
* that all packages in a named module are defined with the properties
* specified by {@link Package}. Otherwise, some {@code Package} objects
* in a named module may be for example sealed with different seal base.
*
* @param name
* The package name
*
* @param specTitle
* The specification title
*
* @param specVersion
* The specification version
*
* @param specVendor
* The specification vendor
*
* @param implTitle
* The implementation title
*
* @param implVersion
* The implementation version
*
* @param implVendor
* The implementation vendor
*
* @param sealBase
* If not {@code null}, then this package is sealed with
* respect to the given code source {@link java.net.URL URL}
* object. Otherwise, the package is not sealed.
*
* @return The newly defined {@code Package} object
*
* @throws NullPointerException
* if {@code name} is {@code null}.
*
* @throws IllegalArgumentException
* if a package of the given {@code name} is already
* defined by this class loader
*
*
* @since 1.2
* @revised 9
*
* @jvms 5.3 Creation and Loading
* @see
* The JAR File Specification: Package Sealing
*/
protected Package definePackage(String name, String specTitle,
String specVersion, String specVendor,
String implTitle, String implVersion,
String implVendor, URL sealBase)
throws IllegalArgumentException
{
Objects.requireNonNull(name);
// definePackage is not final and may be overridden by custom class loader
Package p = new Package(name, specTitle, specVersion, specVendor,
implTitle, implVersion, implVendor,
sealBase, this);
if (packages.putIfAbsent(name, p) != null)
throw new IllegalArgumentException(name);
return p;
}
/**
* Returns a {@code Package} of the given name that
* has been defined by this class loader.
*
* @param name The package name
*
* @return The {@code Package} of the given name that has been defined
* by this class loader, or {@code null} if not found
*
* @throws NullPointerException
* if {@code name} is {@code null}.
*
* @jvms 5.3 Creation and Loading
*
* @since 9
* @hide
*/
public final Package getDefinedPackage(String name) {
Objects.requireNonNull(name, "name cannot be null");
// Android-removed: The module system isn't supported yet.
// NamedPackage p = packages.get(name);
// if (p == null)
// return null;
//
// return definePackage(name, p.module());
return packages.get(name);
}
/**
* Returns all of the {@code Package}s that have been defined by
* this class loader. The returned array has no duplicated {@code Package}s
* of the same name.
*
* @apiNote This method returns an array rather than a {@code Set} or {@code Stream}
* for consistency with the existing {@link #getPackages} method.
*
* @return The array of {@code Package} objects that have been defined by
* this class loader; or an zero length array if no package has been
* defined by this class loader.
*
* @jvms 5.3 Creation and Loading
*
* @since 9
* @hide
*/
public final Package[] getDefinedPackages() {
// Android-changed: Avoid ConcurrentHashNap type of packages.
// return packages().toArray(Package[]::new);
return packages.values().toArray(Package[]::new);
}
// Android-changed: Removed the apinote related to the platform class loader.
// Android-changed: Removed the hidden getDefinedPackage() in the javadoc.
/**
* Finds a package by name in this class loader and its ancestors.
*
* If this class loader defines a {@code Package} of the given name,
* the {@code Package} is returned. Otherwise, the ancestors of
* this class loader are searched recursively (parent by parent)
* for a {@code Package} of the given name.
*
* @param name
* The package name
*
* @return The {@code Package} of the given name that has been defined by
* this class loader or its ancestors, or {@code null} if not found.
*
* @throws NullPointerException
* if {@code name} is {@code null}.
*
* @deprecated
* If multiple class loaders delegate to each other and define classes
* with the same package name, and one such loader relies on the lookup
* behavior of {@code getPackage} to return a {@code Package} from
* a parent loader, then the properties exposed by the {@code Package}
* may not be as expected in the rest of the program.
* For example, the {@code Package} will only expose annotations from the
* {@code package-info.class} file defined by the parent loader, even if
* annotations exist in a {@code package-info.class} file defined by
* a child loader.
*
* @since 1.2
* @revised 9
*/
@Deprecated(since="9")
protected Package getPackage(String name) {
// Android-changed: Keep the deprecated behavior, not the renewed behavior.
/*
Package pkg = getDefinedPackage(name);
if (pkg == null) {
if (parent != null) {
pkg = parent.getPackage(name);
} else {
pkg = BootLoader.getDefinedPackage(name);
}
}
return pkg;
*/
return packages.get(name);
}
// Android-changed: Removed the link to the hidden getDefinedPackages().
// Android-changed: Removed the link to the hidden getPlatformClassLoader().
/**
* Returns all of the {@code Package}s that have been defined by
* this class loader and its ancestors. The returned array may contain
* more than one {@code Package} object of the same package name, each
* defined by a different class loader in the class loader hierarchy.
*
* @return The array of {@code Package} objects that have been defined by
* this class loader and its ancestors
*
* @since 1.2
* @revised 9
*/
protected Package[] getPackages() {
// Android-changed: Keep existing implementation until a bug is found.
// Stream A subpackage of a package named p is any package whose name begins
* with "{@code p.}". For example, {@code javax.swing.text} is a
* subpackage of {@code javax.swing}, and both {@code java.util} and
* {@code java.lang.reflect} are subpackages of {@code java}.
*
* In the event that multiple package defaults apply to a given class,
* the package default pertaining to the most specific package takes
* precedence over the others. For example, if {@code javax.lang} and
* {@code javax.lang.reflect} both have package defaults associated with
* them, the latter package default applies to classes in
* {@code javax.lang.reflect}.
*
* Package defaults take precedence over the class loader's default
* assertion status, and may be overridden on a per-class basis by invoking
* {@link #setClassAssertionStatus(String, boolean)}. If the named class is not a top-level class, this invocation will
* have no effect on the actual assertion status of any class.
* There a limited chance that we end up with multiple Package objects
* representing the same package: It can happen when when a package is
* scattered across different JAR files being loaded by different
* ClassLoaders. Rather unlikely, and given that this whole thing is more or
* less a workaround, probably not worth the effort.
*/
@Override
protected Package getPackage(String name) {
if (name != null && !name.isEmpty()) {
synchronized (this) {
Package pack = super.getPackage(name);
if (pack == null) {
pack = definePackage(name, "Unknown", "0.0", "Unknown", "Unknown", "0.0",
"Unknown", null);
}
return pack;
}
}
return null;
}
@Override
public URL getResource(String resName) {
return findResource(resName);
}
@Override
protected Class> loadClass(String className, boolean resolve)
throws ClassNotFoundException {
Class> clazz = findLoadedClass(className);
if (clazz == null) {
clazz = findClass(className);
}
return clazz;
}
@Override
public Enumeration>, Class>> proxyCache =
new HashMap
>, Class>>();
// The parent class loader for delegation
// Note: VM hardcoded the offset of this field, thus all new fields
// must be added *after* it.
private final ClassLoader parent;
// class loader name
private final String name;
// Android-removed: The module system isn't supported yet.
// the unnamed module for this ClassLoader
// private final Module unnamedModule;
// Android-removed: Remove the unused field.
// a string for exception message printing
// private final String nameAndId;
private static ClassLoader createSystemClassLoader() {
String classPath = System.getProperty("java.class.path", ".");
String librarySearchPath = System.getProperty("java.library.path", "");
// String[] paths = classPath.split(":");
// URL[] urls = new URL[paths.length];
// for (int i = 0; i < paths.length; i++) {
// try {
// urls[i] = new URL("file://" + paths[i]);
// }
// catch (Exception ex) {
// ex.printStackTrace();
// }
// }
//
// return new java.net.URLClassLoader(urls, null);
// TODO Make this a java.net.URLClassLoader once we have those?
return new PathClassLoader(classPath, librarySearchPath, BootClassLoader.getInstance());
}
// Android-removed: Remove unused ParallelLoaders.
/*
* Encapsulates the set of parallel capable loader types.
*//*
private static class ParallelLoaders {
private ParallelLoaders() {}
// the set of parallel capable loader types
private static final Set
*
*
*
*
*
*
* @param module
* The module
* @param name
* The binary name of the class
*
* @return The resulting {@code Class} object in a module defined by
* this class loader, or {@code null} if the class could not be found.
*//*
final Class> loadClass(Module module, String name) {
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
Class> c = findLoadedClass(name);
if (c == null) {
c = findClass(module.getName(), name);
}
if (c != null && c.getModule() == module) {
return c;
} else {
return null;
}
}
}
*/
// Android-removed: ART doesn't expose a class loading lock.
/*
* Returns the lock object for class loading operations.
* For backward compatibility, the default implementation of this method
* behaves as follows. If this ClassLoader object is registered as
* parallel capable, the method returns a dedicated object associated
* with the specified class name. Otherwise, the method returns this
* ClassLoader object.
*
* @param className
* The name of the to-be-loaded class
*
* @return the lock for class loading operations
*
* @throws NullPointerException
* If registered as parallel capable and {@code className} is null
*
* @see #loadClass(String, boolean)
*
* @since 1.7
*//*
protected Object getClassLoadingLock(String className) {
Object lock = this;
if (parallelLockMap != null) {
Object newLock = new Object();
lock = parallelLockMap.putIfAbsent(className, newLock);
if (lock == null) {
lock = newLock;
}
}
return lock;
}
*/
// Android-removed: SecurityManager isn't supported.
/*
// Invoked by the VM after loading class with this loader.
@SuppressWarnings("removal")
private void checkPackageAccess(Class> cls, ProtectionDomain pd) {
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
if (ReflectUtil.isNonPublicProxyClass(cls)) {
for (Class> intf: cls.getInterfaces()) {
checkPackageAccess(intf, pd);
}
return;
}
final String packageName = cls.getPackageName();
if (!packageName.isEmpty()) {
AccessController.doPrivileged(new PrivilegedAction<>() {
public Void run() {
sm.checkPackageAccess(packageName);
return null;
}
}, new AccessControlContext(new ProtectionDomain[] {pd}));
}
}
}
*/
/**
* Finds the class with the specified binary name.
* This method should be overridden by class loader implementations that
* follow the delegation model for loading classes, and will be invoked by
* the {@link #loadClass loadClass} method after checking the
* parent class loader for the requested class.
*
* @implSpec The default implementation throws {@code ClassNotFoundException}.
*
* @param name
* The binary name of the class
*
* @return The resulting {@code Class} object
*
* @throws ClassNotFoundException
* If the class could not be found
*
* @since 1.2
*/
protected Class> findClass(String name) throws ClassNotFoundException {
throw new ClassNotFoundException(name);
}
// Android-removed: The module system isn't supported yet.
/*
* Finds the class with the given binary name
* in a module defined to this class loader.
* Class loader implementations that support loading from modules
* should override this method.
*
* @apiNote This method returns {@code null} rather than throwing
* {@code ClassNotFoundException} if the class could not be found.
*
* @implSpec The default implementation attempts to find the class by
* invoking {@link #findClass(String)} when the {@code moduleName} is
* {@code null}. It otherwise returns {@code null}.
*
* @param moduleName
* The module name; or {@code null} to find the class in the
* {@linkplain #getUnnamedModule() unnamed module} for this
* class loader
* @param name
* The binary name of the class
*
* @return The resulting {@code Class} object, or {@code null}
* if the class could not be found.
*
* @since 9
*//*
protected Class> findClass(String moduleName, String name) {
if (moduleName == null) {
try {
return findClass(name);
} catch (ClassNotFoundException ignore) { }
}
return null;
}
*/
/**
* Converts an array of bytes into an instance of class {@code Class}.
* Before the {@code Class} can be used it must be resolved. This method
* is deprecated in favor of the version that takes a binary name as its first argument, and is more secure.
*
* @param b
* The bytes that make up the class data. The bytes in positions
* {@code off} through {@code off+len-1} should have the format
* of a valid class file as defined by
* The Java Virtual Machine Specification.
*
* @param off
* The start offset in {@code b} of the class data
*
* @param len
* The length of the class data
*
* @return The {@code Class} object that was created from the specified
* class data
*
* @throws ClassFormatError
* If the data did not contain a valid class
*
* @throws IndexOutOfBoundsException
* If either {@code off} or {@code len} is negative, or if
* {@code off+len} is greater than {@code b.length}.
*
* @throws SecurityException
* If an attempt is made to add this class to a package that
* contains classes that were signed by a different set of
* certificates than this class, or if an attempt is made
* to define a class in a package with a fully-qualified name
* that starts with "{@code java.}".
*
* @see #loadClass(String, boolean)
* @see #resolveClass(Class)
*
* @deprecated Replaced by {@link #defineClass(String, byte[], int, int)
* defineClass(String, byte[], int, int)}
*/
@Deprecated(since="1.1")
protected final Class> defineClass(byte[] b, int off, int len)
throws ClassFormatError
{
throw new UnsupportedOperationException("can't load this type of class file");
}
/**
* Converts an array of bytes into an instance of class {@code Class}.
* Before the {@code Class} can be used it must be resolved.
*
*
* ...
* byte[] temp = new byte[bBuffer.{@link
* java.nio.ByteBuffer#remaining remaining}()];
* bBuffer.{@link java.nio.ByteBuffer#get(byte[])
* get}(temp);
* return {@link #defineClass(String, byte[], int, int, ProtectionDomain)
* cl.defineClass}(name, temp, 0,
* temp.length, pd);
*
*
*