java.lang.ClassLoader Maven / Gradle / Ivy
Show all versions of android-all Show documentation
/*
* Copyright (C) 2014 The Android Open Source Project
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. 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.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.AccessController;
import java.security.AccessControlContext;
import java.security.CodeSource;
import java.security.Policy;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain;
import java.security.cert.Certificate;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.Stack;
import java.util.Map;
import java.util.Vector;
import java.util.Hashtable;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import dalvik.system.PathClassLoader;
import java.util.List;
import sun.misc.CompoundEnumeration;
import sun.misc.Resource;
import sun.misc.URLClassPath;
import sun.misc.VM;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import sun.security.util.SecurityConstants;
/**
* A class loader is an object that is responsible for loading classes. The
* class 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 Class Class} object contains a {@link
* Class#getClassLoader() reference} to the ClassLoader that defined
* it.
*
*
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 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.
*
*
The ClassLoader class uses a delegation model to search for
* classes and resources. Each instance of ClassLoader has an
* associated parent class loader. When requested to find a class or
* resource, a ClassLoader instance will delegate the search for the
* class or resource to its parent class loader before attempting to find the
* class or resource itself. The virtual machine's built-in class loader,
* called the "bootstrap class loader", does not itself have a parent but may
* serve as the parent of a ClassLoader instance.
*
*
Class loaders that support concurrent loading of classes are known as
* parallel capable class loaders and are required to register
* themselves at their class initialization time by invoking the
* {@link
* #registerAsParallelCapable ClassLoader.registerAsParallelCapable}
* method. Note that the 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).
*
*
Normally, the Java virtual machine loads classes from the local file
* system in a platform-dependent manner. For example, on UNIX systems, the
* virtual machine loads classes from the directory defined by the
* CLASSPATH environment variable.
*
*
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
* 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 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
* . . .
* }
* }
*
*
* Binary names
*
* Any class name provided as a {@link String} parameter to methods in
* 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"
*
*
* @see #resolveClass(Class)
* @since 1.0
*/
public abstract class ClassLoader {
static private class SystemClassLoader {
public static ClassLoader loader = ClassLoader.createSystemClassLoader();
}
/**
* 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>, 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;
/**
* Encapsulates the set of parallel capable loader types.
*/
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());
}
// The packages defined in this class loader. Each package name is mapped
// to its corresponding Package object.
// @GuardedBy("itself")
private final HashMap packages = new HashMap<>();
/**
* Pointer to the allocator used by the runtime to allocate metadata such
* as ArtFields and ArtMethods.
*/
private transient long allocator;
/**
* Pointer to the class table, only used from within the runtime.
*/
private transient long classTable;
private static Void checkCreateClassLoader() {
return null;
}
private ClassLoader(Void unused, ClassLoader parent) {
this.parent = parent;
}
/**
* Creates a new class loader using the specified parent class loader for
* delegation.
*
* If there is a security manager, its {@link
* SecurityManager#checkCreateClassLoader()
* checkCreateClassLoader} method is invoked. This may result in
* a security exception.
*
* @param parent
* The parent class loader
*
* @throws SecurityException
* If a security manager exists and its
* checkCreateClassLoader method doesn't allow creation
* of a new class loader.
*
* @since 1.2
*/
protected ClassLoader(ClassLoader parent) {
this(checkCreateClassLoader(), parent);
}
/**
* Creates a new class loader using the ClassLoader returned by
* the method {@link #getSystemClassLoader()
* getSystemClassLoader()} as the parent class loader.
*
* If there is a security manager, its {@link
* SecurityManager#checkCreateClassLoader()
* checkCreateClassLoader} method is invoked. This may result in
* a security exception.
*
* @throws SecurityException
* If a security manager exists and its
* checkCreateClassLoader method doesn't allow creation
* of a new class loader.
*/
protected ClassLoader() {
this(checkCreateClassLoader(), getSystemClassLoader());
}
// -- Class --
/**
* Loads the class with the specified binary name.
* This method searches for classes in the same manner as the {@link
* #loadClass(String, boolean)} method. It is invoked by the Java virtual
* machine to resolve class references. Invoking this method is equivalent
* to invoking {@link #loadClass(String, boolean) loadClass(name,
* false)}.
*
* @param name
* The binary name of the class
*
* @return The resulting Class object
*
* @throws ClassNotFoundException
* If the class was not found
*/
public Class loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
}
/**
* 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 null the class
* loader built-in to 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
* resolve flag is true, this method will then invoke the {@link
* #resolveClass(Class)} method on the resulting Class object.
*
*
Subclasses of ClassLoader are encouraged to override {@link
* #findClass(String)}, rather than this method.
*
*
* @param name
* The binary name of the class
*
* @param resolve
* If true then resolve the class
*
* @return The resulting Class object
*
* @throws ClassNotFoundException
* If the class could not be found
*/
// Android-removed: Remove references to getClassLoadingLock
// Remove perf counters.
//
// Unless overridden, this method synchronizes on the result of
// {@link #getClassLoadingLock getClassLoadingLock} method
// during the entire class loading process.
protected Class loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
// First, check if the class has already been loaded
Class c = findLoadedClass(name);
if (c == null) {
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
c = findClass(name);
}
}
return c;
}
/**
* 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. The default implementation
* throws a ClassNotFoundException.
*
* @param name
* The binary name of the class
*
* @return The resulting 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);
}
/**
* Converts an array of bytes into an instance of class Class.
* Before the 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
* off through 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 b of the class data
*
* @param len
* The length of the class data
*
* @return The 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 off or len is negative, or if
* off+len is greater than 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
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 Class.
* Before the Class can be used it must be resolved.
*
*
This method assigns a default {@link java.security.ProtectionDomain
* ProtectionDomain} to the newly defined class. The
* 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 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 ProtectionDomain to the class, use
* the {@link #defineClass(String, byte[], int, int,
* java.security.ProtectionDomain) defineClass} method that takes a
* ProtectionDomain as one of its arguments.
*
* @param name
* The expected binary name of the class, or
* null if not known
*
* @param b
* The bytes that make up the class data. The bytes in positions
* off through 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 b of the class data
*
* @param len
* The length of the class data
*
* @return The 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 off or len is negative, or if
* off+len is greater than 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
* name begins with "java.".
*
* @see #loadClass(String, boolean)
* @see #resolveClass(Class)
* @see java.security.CodeSource
* @see java.security.SecureClassLoader
*
* @since 1.1
*/
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 Class,
* with an optional ProtectionDomain. If the domain is
* null, then a default 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
* ProtectionDomain of the class. Any classes added to that
* package must contain the same set of certificates or a
* SecurityException will be thrown. Note that if
* name is 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.
*
*
The specified name cannot begin with "java.", since
* all classes in the "java.* packages can only be defined by the
* bootstrap class loader. If name is not null, it
* must be equal to the binary name of the class
* specified by the byte array "b", otherwise a {@link
* NoClassDefFoundError NoClassDefFoundError} will be thrown.
*
* @param name
* The expected binary name of the class, or
* null if not known
*
* @param b
* The bytes that make up the class data. The bytes in positions
* off through 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 b of the class data
*
* @param len
* The length of the class data
*
* @param protectionDomain
* The ProtectionDomain of the class
*
* @return The Class object created from the data,
* and optional ProtectionDomain.
*
* @throws ClassFormatError
* If the data did not contain a valid class
*
* @throws NoClassDefFoundError
* If name is not equal to the binary
* name of the class specified by b
*
* @throws IndexOutOfBoundsException
* If either off or len is negative, or if
* off+len is greater than 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 name begins with
* "java.".
*/
// Android-changed: Remove from link for NoClassDefFoundError
protected final Class defineClass(String name, byte[] b, int off, int len,
ProtectionDomain protectionDomain)
throws ClassFormatError
{
throw new UnsupportedOperationException("can't load this type of class file");
}
/**
* Converts a {@link java.nio.ByteBuffer ByteBuffer}
* into an instance of class Class,
* with an optional ProtectionDomain. If the domain is
* null, then a default 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, and the restrictions on class names
* 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.defineClass(name,
* bBuffer, pd) yields exactly the same
* result as the statements
*
*
* ...
* 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);
*
*
* @param name
* The expected binary name. of the class, or
* null if not known
*
* @param b
* The bytes that make up the class data. The bytes from positions
* b.position() through b.position() + b.limit() -1
* should have the format of a valid class file as defined by
* The Java™ Virtual Machine Specification.
*
* @param protectionDomain
* The ProtectionDomain of the class, or null.
*
* @return The Class object created from the data,
* and optional ProtectionDomain.
*
* @throws ClassFormatError
* If the data did not contain a valid class.
*
* @throws NoClassDefFoundError
* If name is not equal to the binary
* name of the class specified by b
*
* @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 name begins with
* "java.".
*
* @see #defineClass(String, byte[], int, int, ProtectionDomain)
*
* @since 1.5
*/
protected final Class defineClass(String name, java.nio.ByteBuffer b,
ProtectionDomain protectionDomain)
throws ClassFormatError
{
throw new UnsupportedOperationException("can't load this type of class file");
}
/**
* Links the specified class. This (misleadingly named) method may be
* used by a class loader to link a class. If the class c has
* already been linked, then this method simply returns. Otherwise, the
* class is linked as described in the "Execution" chapter of
* The Java™ Language Specification.
*
* @param c
* The class to link
*
* @throws NullPointerException
* If c is null.
*
* @see #defineClass(String, byte[], int, int)
*/
protected final void resolveClass(Class c) {
}
/**
* Finds a class with the specified binary name,
* loading it if necessary.
*
* This method loads the class through the system class loader (see
* {@link #getSystemClassLoader()}). The Class object returned
* might have more than one ClassLoader associated with it.
* Subclasses of ClassLoader need not usually invoke this method,
* because most class loaders need to override just {@link
* #findClass(String)}.
*
* @param name
* The binary name of the class
*
* @return The Class object for the specified name
*
* @throws ClassNotFoundException
* If the class could not be found
*
* @see #ClassLoader(ClassLoader)
* @see #getParent()
*/
protected final Class findSystemClass(String name)
throws ClassNotFoundException
{
return Class.forName(name, false, getSystemClassLoader());
}
/**
* Returns a class loaded by the bootstrap class loader;
* or return null if not found.
*/
private Class findBootstrapClassOrNull(String name)
{
return null;
}
/**
* Returns the class with the given binary name if this
* loader has been recorded by the Java virtual machine as an initiating
* loader of a class with that binary name. Otherwise
* null is returned.
*
* @param name
* The binary name of the class
*
* @return The Class object, or null if the class has
* not been loaded
*
* @since 1.1
*/
protected final Class findLoadedClass(String name) {
ClassLoader loader;
if (this == BootClassLoader.getInstance())
loader = null;
else
loader = this;
return VMClassLoader.findLoadedClass(loader, name);
}
/**
* Sets the signers of a class. This should be invoked after defining a
* class.
*
* @param c
* The Class object
*
* @param signers
* The signers for the class
*
* @since 1.1
*/
protected final void setSigners(Class c, Object[] signers) {
}
// -- Resource --
/**
* Finds the resource with the given name. A resource is some data
* (images, audio, text, etc) that can be accessed by class code in a way
* that is independent of the location of the code.
*
* The name of a resource is a '/'-separated path name that
* identifies the resource.
*
*
This method will first search the parent class loader for the
* resource; if the parent is null the path of the class loader
* built-in to the virtual machine is searched. That failing, this method
* will invoke {@link #findResource(String)} to find the resource.
*
* @apiNote When overriding this method it is recommended that an
* implementation ensures that any delegation is consistent with the {@link
* #getResources(java.lang.String) getResources(String)} method.
*
* @param name
* The resource name
*
* @return A URL object for reading the resource, or
* null if the resource could not be found or the invoker
* doesn't have adequate privileges to get the resource.
*
* @since 1.1
*/
public URL getResource(String name) {
URL url;
if (parent != null) {
url = parent.getResource(name);
} else {
url = getBootstrapResource(name);
}
if (url == null) {
url = findResource(name);
}
return url;
}
/**
* Finds all the resources with the given name. A resource is some data
* (images, audio, text, etc) that can be accessed by class code in a way
* that is independent of the location of the code.
*
* The name of a resource is a /-separated path name that
* identifies the resource.
*
*
The search order is described in the documentation for {@link
* #getResource(String)}.
*
* @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 Enumeration's
* {@code nextElement} method is the same resource that the
* {@code getResource(String)} method would return.
*
* @param name
* The resource name
*
* @return An enumeration of {@link java.net.URL URL} objects for
* the resource. If no resources could be found, the enumeration
* will be empty. Resources that the class loader doesn't have
* access to will not be in the enumeration.
*
* @throws IOException
* If I/O errors occur
*
* @see #findResources(String)
*
* @since 1.2
*/
public Enumeration getResources(String name) throws IOException {
@SuppressWarnings("unchecked")
Enumeration[] tmp = (Enumeration[]) new Enumeration[2];
if (parent != null) {
tmp[0] = parent.getResources(name);
} else {
tmp[0] = getBootstrapResources(name);
}
tmp[1] = findResources(name);
return new CompoundEnumeration<>(tmp);
}
/**
* Finds the resource with the given name. Class loader implementations
* should override this method to specify where to find resources.
*
* @param name
* The resource name
*
* @return A URL object for reading the resource, or
* null if the resource could not be found
*
* @since 1.2
*/
protected URL findResource(String name) {
return null;
}
/**
* Returns an enumeration of {@link java.net.URL URL} objects
* representing all the resources with the given name. Class loader
* implementations should override this method to specify where to load
* resources from.
*
* @param name
* The resource name
*
* @return An enumeration of {@link java.net.URL URL} objects for
* the resources
*
* @throws IOException
* If I/O errors occur
*
* @since 1.2
*/
protected Enumeration findResources(String name) throws IOException {
return java.util.Collections.emptyEnumeration();
}
/**
* Registers the caller as parallel capable.
* The registration succeeds if and only if all of the following
* conditions are met:
*
* - no instance of the caller has been created
* - all of the super classes (except class Object) of the caller are
* registered as parallel capable
*
* Note that once a class loader is registered as parallel capable, there
* is no way to change it back.
*
* @return true if the caller is successfully registered as
* parallel capable and false if otherwise.
*
* @since 1.7
*/
@CallerSensitive
protected static boolean registerAsParallelCapable() {
return true;
}
/**
* Find a resource of the specified name from the search path used to load
* classes. This method locates the resource through the system class
* loader (see {@link #getSystemClassLoader()}).
*
* @param name
* The resource name
*
* @return A {@link java.net.URL URL} object for reading the
* resource, or null if the resource could not be found
*
* @since 1.1
*/
public static URL getSystemResource(String name) {
ClassLoader system = getSystemClassLoader();
if (system == null) {
return getBootstrapResource(name);
}
return system.getResource(name);
}
/**
* Finds all resources of the specified name from the search path used to
* load classes. The resources thus found are returned as an
* {@link java.util.Enumeration Enumeration} of {@link
* java.net.URL URL} objects.
*
* The search order is described in the documentation for {@link
* #getSystemResource(String)}.
*
* @param name
* The resource name
*
* @return An enumeration of resource {@link java.net.URL URL}
* objects
*
* @throws IOException
* If I/O errors occur
* @since 1.2
*/
public static Enumeration getSystemResources(String name)
throws IOException
{
ClassLoader system = getSystemClassLoader();
if (system == null) {
return getBootstrapResources(name);
}
return system.getResources(name);
}
/**
* Find resources from the VM's built-in classloader.
*/
private static URL getBootstrapResource(String name) {
return null;
}
/**
* Find resources from the VM's built-in classloader.
*/
private static Enumeration getBootstrapResources(String name)
throws IOException
{
return null;
}
/**
* Returns an input stream for reading the specified resource.
*
* The search order is described in the documentation for {@link
* #getResource(String)}.
*
* @param name
* The resource name
*
* @return An input stream for reading the resource, or null
* if the resource could not be found
*
* @since 1.1
*/
public InputStream getResourceAsStream(String name) {
URL url = getResource(name);
try {
return url != null ? url.openStream() : null;
} catch (IOException e) {
return null;
}
}
/**
* Open for reading, a resource of the specified name from the search path
* used to load classes. This method locates the resource through the
* system class loader (see {@link #getSystemClassLoader()}).
*
* @param name
* The resource name
*
* @return An input stream for reading the resource, or null
* if the resource could not be found
*
* @since 1.1
*/
public static InputStream getSystemResourceAsStream(String name) {
URL url = getSystemResource(name);
try {
return url != null ? url.openStream() : null;
} catch (IOException e) {
return null;
}
}
// -- Hierarchy --
/**
* Returns the parent class loader for delegation. Some implementations may
* use null to represent the bootstrap class loader. This method
* will return null in such implementations if this class loader's
* parent is the bootstrap class loader.
*
* If a security manager is present, and the invoker's class loader is
* not null and is not an ancestor of this class loader, then this
* method invokes the security manager's {@link
* SecurityManager#checkPermission(java.security.Permission)
* checkPermission} method with a {@link
* RuntimePermission#RuntimePermission(String)
* RuntimePermission("getClassLoader")} permission to verify
* access to the parent class loader is permitted. If not, a
* SecurityException will be thrown.
*
* @return The parent ClassLoader
*
* @throws SecurityException
* If a security manager exists and its checkPermission
* method doesn't allow access to this class loader's parent class
* loader.
*
* @since 1.2
*/
@CallerSensitive
public final ClassLoader getParent() {
return parent;
}
// Android-changed: Removed "java.system.class.loader" paragraph.
/**
* Returns the system class loader for delegation. This is the default
* delegation parent for new ClassLoader instances, and is
* typically the class loader used to start the application.
*
* This method is first invoked early in the runtime's startup
* sequence, at which point it creates the system class loader and sets it
* as the context class loader of the invoking Thread.
*
*
The default system class loader is an implementation-dependent
* instance of this class.
*
*
If a security manager is present, and the invoker's class loader is
* not null and the invoker's class loader is not the same as or
* an ancestor of the system class loader, then this method invokes the
* security manager's {@link
* SecurityManager#checkPermission(java.security.Permission)
* checkPermission} method with a {@link
* RuntimePermission#RuntimePermission(String)
* RuntimePermission("getClassLoader")} permission to verify
* access to the system class loader. If not, a
* SecurityException will be thrown.
*
* @return The system ClassLoader for delegation, or
* null if none
*
* @throws SecurityException
* If a security manager exists and its checkPermission
* method doesn't allow access to the system class loader.
*
* @throws IllegalStateException
* If invoked recursively during the construction of the class
* loader specified by the "java.system.class.loader"
* property.
*
* @throws Error
* If the system property "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
*/
@CallerSensitive
public static ClassLoader getSystemClassLoader() {
return SystemClassLoader.loader;
}
// -- Package --
/**
* Defines a package by name in this ClassLoader. This allows
* class loaders to define the packages for their classes. Packages must
* be created before the class is defined, and package names must be
* unique within a class loader and cannot be redefined or changed once
* created.
*
* @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 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 Package object
*
* @throws IllegalArgumentException
* If package name duplicates an existing package either in this
* class loader or one of its ancestors
*
* @since 1.2
*/
protected Package definePackage(String name, String specTitle,
String specVersion, String specVendor,
String implTitle, String implVersion,
String implVendor, URL sealBase)
throws IllegalArgumentException
{
synchronized (packages) {
Package pkg = packages.get(name);
if (pkg != null) {
throw new IllegalArgumentException(name);
}
pkg = new Package(name, specTitle, specVersion, specVendor,
implTitle, implVersion, implVendor,
sealBase, this);
packages.put(name, pkg);
return pkg;
}
}
/**
* Returns a Package that has been defined by this class loader
* or any of its ancestors.
*
* @param name
* The package name
*
* @return The Package corresponding to the given name, or
* null if not found
*
* @since 1.2
*/
protected Package getPackage(String name) {
Package pkg;
synchronized (packages) {
pkg = packages.get(name);
}
return pkg;
}
/**
* Returns all of the Packages defined by this class loader and
* its ancestors.
*
* @return The array of Package objects defined by this
* ClassLoader
*
* @since 1.2
*/
protected Package[] getPackages() {
Map map;
synchronized (packages) {
map = new HashMap<>(packages);
}
Package[] pkgs;
return map.values().toArray(new Package[map.size()]);
}
// -- Native library access --
/**
* Returns the absolute path name of a native library. The VM invokes this
* method to locate the native libraries that belong to classes loaded with
* this class loader. If this method returns null, the VM
* searches the library along the path specified as the
* "java.library.path" property.
*
* @param libname
* The library name
*
* @return The absolute path of the native library
*
* @see System#loadLibrary(String)
* @see System#mapLibraryName(String)
*
* @since 1.2
*/
protected String findLibrary(String libname) {
return null;
}
/**
* Sets the default assertion status for this class loader. This setting
* determines whether classes loaded by this class loader and initialized
* in the future will have assertions enabled or disabled by default.
* This setting may be overridden on a per-package or per-class basis by
* invoking {@link #setPackageAssertionStatus(String, boolean)} or {@link
* #setClassAssertionStatus(String, boolean)}.
*
* @param enabled
* true if classes loaded by this class loader will
* henceforth have assertions enabled by default, false
* if they will have assertions disabled by default.
*
* @since 1.4
*/
public void setDefaultAssertionStatus(boolean enabled) {
}
/**
* Sets the package default assertion status for the named package. The
* package default assertion status determines the assertion status for
* classes initialized in the future that belong to the named package or
* any of its "subpackages".
*
* A subpackage of a package named p is any package whose name begins
* with "p.". For example, javax.swing.text is a
* subpackage of javax.swing, and both java.util and
* java.lang.reflect are subpackages of 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 javax.lang and
* javax.lang.reflect both have package defaults associated with
* them, the latter package default applies to classes in
* 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)}.
*
* @param packageName
* The name of the package whose package default assertion status
* is to be set. A null value indicates the unnamed
* package that is "current"
* (see section 7.4.2 of
* The Java™ Language Specification.)
*
* @param enabled
* true if classes loaded by this classloader and
* belonging to the named package or any of its subpackages will
* have assertions enabled by default, false if they will
* have assertions disabled by default.
*
* @since 1.4
*/
public void setPackageAssertionStatus(String packageName,
boolean enabled) {
}
/**
* Sets the desired assertion status for the named top-level class in this
* class loader and any nested classes contained therein. This setting
* takes precedence over the class loader's default assertion status, and
* over any applicable per-package default. This method has no effect if
* the named class has already been initialized. (Once a class is
* initialized, its assertion status cannot change.)
*
* If the named class is not a top-level class, this invocation will
* have no effect on the actual assertion status of any class.
*
* @param className
* The fully qualified class name of the top-level class whose
* assertion status is to be set.
*
* @param enabled
* true if the named class is to have assertions
* enabled when (and if) it is initialized, false if the
* class is to have assertions disabled.
*
* @since 1.4
*/
public void setClassAssertionStatus(String className, boolean enabled) {
}
/**
* Sets the default assertion status for this class loader to
* false and discards any package defaults or class assertion
* status settings associated with the class loader. This method is
* provided so that class loaders can be made to ignore any command line or
* persistent assertion status settings and "start with a clean slate."
*
* @since 1.4
*/
public void clearAssertionStatus() {
/*
* Whether or not "Java assertion maps" are initialized, set
* them to empty maps, effectively ignoring any present settings.
*/
}
}
class BootClassLoader extends ClassLoader {
private static BootClassLoader instance;
@FindBugsSuppressWarnings("DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED")
public static synchronized BootClassLoader getInstance() {
if (instance == null) {
instance = new BootClassLoader();
}
return instance;
}
public BootClassLoader() {
super(null);
}
@Override
protected Class findClass(String name) throws ClassNotFoundException {
return Class.classForName(name, false, null);
}
@Override
protected URL findResource(String name) {
return VMClassLoader.getResource(name);
}
@SuppressWarnings("unused")
@Override
protected Enumeration findResources(String resName) throws IOException {
return Collections.enumeration(VMClassLoader.getResources(resName));
}
/**
* Returns package information for the given package. Unfortunately, the
* Android BootClassLoader doesn't really have this information, and as a
* non-secure ClassLoader, it isn't even required to, according to the spec.
* Yet, we want to provide it, in order to make all those hopeful callers of
* {@code myClass.getPackage().getName()} happy. Thus we construct a Package
* object the first time it is being requested and fill most of the fields
* with dummy values. The Package object is then put into the ClassLoader's
* Package cache, so we see the same one next time. We don't create Package
* objects for null arguments or for the default package.
*
* 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 getResources(String resName) throws IOException {
return findResources(resName);
}
}