/*
* @(#)ClassLoader.java 1.162 02/03/19
*
* Copyright 2002 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
import java.io.InputStream;
import java.io.IOException;
import java.io.ClassLoader is an abstract class.
* Given the 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 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 called upon 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.
*
* 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
* defineClass converts an array of bytes into an
* instance of class Class. Instances of this newly
* defined class can be created using the newInstance
* method in class Class.
*
* 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 calls the 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
* 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 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
* . . .
* }
* }
*
* If there is a security manager, its checkCreateClassLoader
* method is called. 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.
* @see java.lang.SecurityException
* @see java.lang.SecurityManager#checkCreateClassLoader()
* @since 1.2
*/
protected ClassLoader(ClassLoader parent) {
ClassLoader
* returned by the method getSystemClassLoader() as the
* parent class loader.
*
* If there is a security manager, its checkCreateClassLoader
* method is called. 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.
*
* @see java.lang.SecurityException
* @see java.lang.SecurityManager#checkCreateClassLoader()
*/
protected ClassLoader() {
loadClass(name, false).
*
* @param name the name of the class
* @return the resulting Class object
* @exception ClassNotFoundException if the class was not found
*/
public Class loadClass(String name) throws ClassNotFoundException
{
return loadClass(name, false);
}
/**
* Loads the class with the specified name. The default implementation of
* this method searches for classes in the following order:
* *
*
loadClass method on the parent class
* loader. If the parent is null the class loader
* built-in to the virtual machine is used, instead. *
*
resolve flag is true, this method will then call the
* {@link #resolveClass(Class)} method on the resulting class object.
* * From the Java 2 SDK, v1.2, subclasses of ClassLoader are * encouraged to override * {@link #findClass(String)}, rather than this method.
*
* @param name the name of the class
* @param resolve if true then resolve the class
* @return the resulting Class object
* @exception ClassNotFoundException if the class could not be found
*/
protected synchronized 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 = findBootstrapClass0(name);
}
} catch (ClassNotFoundException e) {
// If still not found, then call findClass in order
// to find the class.
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
/*
* This method is called by the virtual machine to load
* a class.
*/
private synchronized Class loadClassInternal(String name)
throws ClassNotFoundException {
return loadClass(name);
}
private void checkPackageAccess(Class cls, loadClass
* method after checking the parent class loader for the requested class.
* The default implementation throws ClassNotFoundException.
*
* @param name the name of the class
* @return the resulting Class object
* @exception 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 the class 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
* @exception ClassFormatError if the data did not contain a valid class
* @exception IndexOutOfBoundsException if either off or
* len is negative, or if
* off+len is greater than b.length.
* @see ClassLoader#loadClass(java.lang.String, boolean)
* @see ClassLoader#resolveClass(java.lang.Class)
* @deprecated Replaced by defineClass(java.lang.String, byte[], int, int)
*/
protected final Class defineClass(byte[] b, int off, int len)
throws Class.
* Before the Class can be used it must be resolved.
*
* This method assigns a default ProtectionDomain to
* the newly defined class. The ProtectionDomain
* contains the set of permissions granted when
* a call to Policy.getPolicy().getPermissions() is made with
* a code source of null,null. The default domain is
* created on the first invocation of defineClass, and
* re-used on subsequent calls.
*
* To assign a specific ProtectionDomain to the class,
* use the defineClass method that takes a
* ProtectionDomain as one of its arguments.
*
* @param name the expected name of the class, or null
* if not known, using '.' and not '/' as the separator
* and without a trailing ".class" suffix.
* @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
* @exception ClassFormatError if the data did not contain a valid class
* @exception IndexOutOfBoundsException if either off or
* len is negative, or if
* off+len is greater than b.length.
* @exception 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 the class name begins with "java.".
*
* @see ClassLoader#loadClass(java.lang.String, boolean)
* @see ClassLoader#resolveClass(java.lang.Class)
* @see java.security.ProtectionDomain
* @see java.security.Policy
* @see java.security.CodeSource
* @see java.security.SecureClassLoader
* @since JDK1.1
*/
protected final Class defineClass(String name, byte[] b, int off, int len)
throws 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
* 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 the name argument is
* null, this check is not performed. You should always pass in the
* 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 class name cannot begin with "java.", since all
* classes in the java.* packages can only be defined by the bootstrap
* class loader. If the name parameter is not null, it
* must be equal to the name of the class specified by the byte
* array b, otherwise a ClassFormatError is raised.
*
* @param name the expected name of the class, or null
* if not known, using '.' and not '/' as the separator
* and without a trailing ".class" suffix.
* @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.
* @exception ClassFormatError if the data did not contain a valid class
* @exception IndexOutOfBoundsException if either off or
* len is negative, or if
* off+len is greater than b.length.
* @exception 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
* the class name begins with "java.".
*/
protected final Class defineClass(String name, byte[] b, int off, int len,
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
* @exception NullPointerException if c is null.
* @see java.lang.ClassLoader#defineClass(java.lang.String,byte[],int,int)
*/
protected final void resolveClass(Class c) {
check();
resolveClass0(c);
}
/**
* Finds a class with the specified name, loading it if necessary.
* * Prior to the Java 2 SDK, this method loads a class from the local file * system in a platform-dependent manner, and returns a class object * that has no associated class loader.
*
* Since the Java 2 SDK v1.2, this method loads the class through the
* system class loader(see {@link #getSystemClassLoader()}). Class objects
* returned might have ClassLoaders associated with them.
* Subclasses of ClassLoader need not usually call this
* method, because most class loaders need to override just {@link
* #findClass(String)}.
*
* @param name the name of the class that is to be found
* @return the Class object for the specified
* name
* @exception ClassNotFoundException if the class could not be found
* @see #ClassLoader(ClassLoader)
* @see #getParent()
*/
protected final Class findSystemClass(String name)
throws ClassNotFoundException
{
check();
ClassLoader system = getSystemClassLoader();
if (system == null) {
return findBootstrapClass(name);
}
return system.loadClass(name);
}
/**
* 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 caller's class loader is
* not null and is not an ancestor of this class loader, then
* this method calls the security manager's checkPermission
* method with a RuntimePermission("getClassLoader")
* permission to ensure it's ok to access the parent class loader.
* 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.
*
* @see SecurityManager#checkPermission
* @see java.lang.RuntimePermission
*
* @since 1.2
*/
public final ClassLoader getParent() {
if (parent == null)
return null;
Class object
* @param signers the signers for the class
* @since JDK1.1
*/
protected final void setSigners(Class c, Object[] signers) {
check();
c.Class object, or null if
* the class has not been loaded
* @since JDK1.1
*/
protected native final Class findLoadedClass(String name);
/**
* 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 call findResource to find the resource.
*
* @param name resource name
* @return a URL for reading the resource, or null if
* the resource could not be found or the caller doesn't have
* adequate privileges to get the resource.
* @since JDK1.1
* @see #findResource(String)
*/
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)}.
*
* @param name resource name
* @return an enumeration of URL to the resource. If no resources could
* be found, the enumeration will be empty. Resources that the
* doesn't have access to will not be in the enumeration.
* @throws IOException if I/O errors occur
* @since 1.2
* @see #getResource
* @see #findResources
*/
public final Enumeration getResources(String name) throws IOException {
Enumeration[] tmp = new Enumeration[2];
if (parent != null) {
tmp[0] = parent.getResources(name);
} else {
tmp[0] = getBootstrapResources(name);
}
tmp[1] = findResources(name);
return new null
* if the resource could not be found
* @since 1.2
*/
protected URL findResource(String name) {
return null;
}
/**
* Find a resource of the specified name from the search path used to load
* classes.
* * In JDK1.1, the search path used is that of the virtual machine's * built-in class loader.
*
* Since the Java 2 SDK v1.2, this method locates the resource through the system class
* loader (see {@link #getSystemClassLoader()}).
*
* @param name the resource name
* @return a URL for reading the resource, or null if
* the resource could not be found
* @since JDK1.1
*/
public static URL getSystemResource(String name) {
ClassLoader system = getSystemClassLoader();
if (system == null) {
return getBootstrapResource(name);
}
return system.getResource(name);
}
/**
* Find resources from the VM's built-in classloader.
*/
private static URL getBootstrapResource(String name) {
Enumeration of URL objects.
* * The search order is described in the documentation for {@link * #getSystemResource(String)}.
*
* @param name the resource name
* @return an enumeration of resource URLs
* @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 Enumeration getBootstrapResources(String name)
throws IOException
{
final Enumeration e = getBootstrapClassPath().
*
* @param name the resource name
* @return an input stream for reading the resource, or null
* if the resource could not be found
* @since JDK1.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.
* * The search order is described in the documentation for {@link * #getSystemResource(String)}.
*
* @param name the resource name
* @return an input stream for reading the resource, or null
* if the resource could not be found
* @since JDK1.1
*/
public static InputStream getSystemResourceAsStream(String name) {
URL url = getSystemResource(name);
try {
return url != null ? url.openStream() : null;
} catch (IOException e) {
return null;
}
}
/**
* 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 the system property java.system.class.loader is * defined when this method is first invoked then the value of that * property is taken to be the name of a class that will be returned as * the system class loader. The class is loaded using the default system * class loader and must define a public constructor that takes a single * parameter of type ClassLoader which is used * as the delegation parent. An instance is then created using this * constructor with the default system class loader as the parameter. * The resulting class loader is defined to be the system class loader. *
* If a security manager is present, and the caller's class loader is
* not null and the caller's class loader is not the same as or an ancestor of
* the system class loader, then
* this method calls the security manager's checkPermission
* method with a RuntimePermission("getClassLoader")
* permission to ensure it's ok to access 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.
* @see SecurityManager#checkPermission
* @see java.lang.RuntimePermission
* @revised 1.4
*/
public static ClassLoader getSystemClassLoader() {
initSystemClassLoader();
if (scl == null) {
return null;
}
Package object
* @exception IllegalArgumentException if package name duplicates an
* existing package either in this class loader or one of
* its ancestors
* @since 1.2
*/
protected Package objects defined by this
* ClassLoader
* @since 1.2
*/
protected 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 java.lang.System#loadLibrary(java.lang.String)
* @see java.lang.System#mapLibraryName(java.lang.String)
* @since 1.2
*/
protected String findLibrary(String libname) {
return null;
}
/**
* The inner class NativeLibrary denotes a loaded native library
* instance. Every classloader contains a vector of loaded native
* libraries in the private field nativeLibraries.
* The native libraries loaded into the system are entered into
* the systemNativeLibraries vector.
*
* Every native library reuqires a particular version of JNI. This
* is denoted by the private jniVersion field. This field is set
* by the VM when it loads the library, and used by the VM to pass
* the correct version of JNI to the native methods.
*
* @version 1.162, 03/19/02
* @see java.lang.ClassLoader
* @since 1.2
*/
static class NativeLibrary {
/* opaque handle to native library, used in native code. */
long handle;
/* the version of JNI environment the native library requires. */
private int jniVersion;
/* the class from which the library is loaded, also indicates
the loader this native library belongs. */
private Class fromClass;
/* the canonicalized name of the native library. */
String name;
native void load(String name);
native long find(String name);
native void unload();
public NativeLibrary(Class fromClass, String name) {
this.name = name;
this.fromClass = fromClass;
}
protected void finalize() {
synchronized (loadedLibraryNames) {
if (fromClass.getClassLoader() != null && handle != 0) {
/* remove the native library name */
int size = loadedLibraryNames.
* 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" * (JLS 7.4.2). * @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 synchronized void setPackageAssertionStatus(String packageName, boolean enabled) { if (packageAssertionStatus == null) initializeJavaAssertionMaps(); packageAssertionStatus.put(packageName, Boolean.valueOf(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 call will have no
* effect on the actual assertion status of any class, and its return
* value is undefined.
*
* @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 synchronized void setClassAssertionStatus(String className,
boolean enabled)
{
if (classAssertionStatus == null)
initializeJavaAssertionMaps();
classAssertionStatus.put(className, Boolean.valueOf(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 call 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 synchronized void clearAssertionStatus() {
/*
* Whether or not "Java assertion maps" are initialized, set
* them to empty maps, effectively ignoring any present settings.
*/
classAssertionStatus = new HashMap();
packageAssertionStatus = new HashMap();
defaultAssertionStatus = false;
}
/**
* Returns the assertion status that would be assigned to the specified
* class if it were to be initialized at the time this method is invoked.
* If the named class has had its assertion status set, the most recent
* setting will be returned; otherwise, if any package default assertion
* status pertains to this class, the most recent setting for the most
* specific pertinent package default assertion status is returned;
* otherwise, this class loader's default assertion status is returned.
*
* @param className the fully qualified class name of the class whose
* desired assertion status is being queried.
* @return the desired assertion status of the specified class.
* @see #setClassAssertionStatus(String,boolean)
* @see #setPackageAssertionStatus(String,boolean)
* @see #setDefaultAssertionStatus(boolean)
* @since 1.4
*/
synchronized boolean desiredAssertionStatus(String className) {
Boolean result;
// assert classAssertionStatus != null;
// assert packageAssertionStatus != null;
// Check for a class entry
result = (Boolean)classAssertionStatus.get(className);
if (result != null)
return result.booleanValue();
// Check for most specific package entry
int dotIndex = className.lastIndexOf(".");
if (dotIndex < 0) { // default package
result = (Boolean)packageAssertionStatus.get(null);
if (result != null)
return result.booleanValue();
}
while(dotIndex > 0) {
className = className.substring(0, dotIndex);
result = (Boolean)packageAssertionStatus.get(className);
if (result != null)
return result.booleanValue();
dotIndex = className.lastIndexOf(".", dotIndex-1);
}
// Return the classloader default
return defaultAssertionStatus;
}
// Set up the assertions with information provided by the VM.
private void initializeJavaAssertionMaps() {
// assert Thread.holdsLock(this);
classAssertionStatus = new HashMap();
packageAssertionStatus = new HashMap();