home *** CD-ROM | disk | FTP | other *** search
Java Source | 1998-03-20 | 32.7 KB | 980 lines |
- /*
- * @(#)ClassLoader.java 1.91 98/03/18
- *
- * Copyright 1994-1998 by Sun Microsystems, Inc.,
- * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
- * All rights reserved.
- *
- * This software is the confidential and proprietary information
- * of Sun Microsystems, Inc. ("Confidential Information"). You
- * shall not disclose such Confidential Information and shall use
- * it only in accordance with the terms of the license agreement
- * you entered into with Sun.
- */
-
- package java.lang;
-
- import java.io.InputStream;
- import java.io.IOException;
- import java.io.StringWriter;
- import java.io.PrintWriter;
- import java.util.Hashtable;
- import java.util.Enumeration;
- import java.util.Vector;
- import java.util.Stack;
- import java.util.NoSuchElementException;
- import java.net.URL;
- import java.net.MalformedURLException;
- import java.security.AccessController;
- import java.security.ProtectionDomain;
- import java.security.CodeSource;
- import java.security.Policy;
- import sun.misc.URLClassPath;
- import sun.misc.Resource;
- import sun.misc.CompoundEnumeration;
- import sun.misc.Launcher;
-
- /**
- * The class <code>ClassLoader</code> is an abstract class.
- * Applications implement subclasses of <code>ClassLoader</code> in
- * order to extend the manner in which the Java Virtual Machine
- * dynamically loads classes.
- * <p>
- * 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 <code>CLASSPATH</code> environment variable.
- * <p>
- * 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
- * <code>defineClass</code> converts an array of bytes into an
- * instance of class <code>Class</code>. Instances of this newly
- * defined class can be created using the <code>newInstance</code>
- * method in class <code>Class</code>.
- * <p>
- * 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 <code>loadClass</code>
- * method of the class loader that originally created the class. If
- * the Java Virtual Machine only needs to determine if the class
- * exists and if it does exist to know its superclass, the
- * <code>resolve</code> flag is set to <code>false</code>. However,
- * if an instance of the class is being created or any of its methods
- * are being called, the class must also be resolved. In this case
- * the <code>resolve</code> flag is set to <code>true</code>, and the
- * <code>resolveClass</code> method should be called.
- * <p>
- * For example, an application could create a network class loader
- * to download class files from a server. Sample code might look like:
- * <blockquote><pre>
- * ClassLoader loader = new NetworkClassLoader(host, port);
- * Object main = loader.loadClass("Main", true).newInstance();
- * . . .
- * </pre></blockquote>
- * <p>
- * The network class loader subclass must define the method
- * <code>loadClass</code> to load a class from the network. Once it
- * has downloaded the bytes that make up the class, it should use the
- * method <code>defineClass</code> to create a class instance. A
- * sample implementation is:
- * <p><hr><blockquote><pre>
- * class NetworkClassLoader extends ClassLoader {
- * String host;
- * int port;
- *
- * public Class findLocalClass(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
- * . . .
- * }
- * }
- * </pre></blockquote><hr>
- *
- * @version 1.91, 03/18/98
- * @see java.lang.Class
- * @see java.lang.Class#newInstance()
- * @see java.lang.ClassLoader#defineClass(byte[], int, int)
- * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
- * @see java.lang.ClassLoader#resolveClass(java.lang.Class)
- * @since JDK1.0
- */
- public abstract class ClassLoader {
- /*
- * If initialization succeed this is set to true and security checks will
- * succeed. Otherwise the object is not initialized and the object is
- * useless.
- */
- private boolean initialized = false;
-
- /*
- * The parent class loader for delegation.
- */
- private ClassLoader parent;
-
- /*
- * The classes loaded by this class loader. Each class name is mapped
- * to its corresponding Class object.
- */
- private Hashtable classes = new Hashtable();
-
- /*
- * The packages defined in this class loader. Each package name is
- * mapped to its corresponding Package object.
- */
- private Hashtable packages = new Hashtable();
-
- /**
- * Creates a new class loader using the specified parent class loader
- * for delegation.
- * <p>
- * If there is a security manager, its <code>checkCreateClassLoader</code>
- * method is called. This may result in a security exception.
- *
- * @exception SecurityException if the current thread does not have
- * permission to create a new class loader
- * @see java.lang.SecurityException
- * @see java.lang.SecurityManager#checkCreateClassLoader()
- * @since JDK1.2
- */
- protected ClassLoader(ClassLoader parent) {
- SecurityManager security = System.getSecurityManager();
- if (security != null) {
- security.checkCreateClassLoader();
- }
- this.parent = parent;
- initialized = true;
- }
-
- /**
- * Creates a new class loader using the <code>ClassLoader</code>
- * returned by the method <code>getBaseClassLoader()</code> as the
- * parent class loader.
- * <p>
- * If there is a security manager, its <code>checkCreateClassLoader</code>
- * method is called. This may result in a security exception.
- *
- * @exception SecurityException if the current thread does not have
- * permission to create a new class loader
- * @see java.lang.SecurityException
- * @see java.lang.SecurityManager#checkCreateClassLoader()
- */
- protected ClassLoader() {
- this(getBaseClassLoader());
- }
-
- /**
- * Loads the class with the specified name. The <code>resolveClass</code>
- * method will be called on the resulting <code>Class</code> object.
- *
- * @param name the name of the class
- * @return the resulting <code>Class</code> object
- * @see #resolveClass
- * @exception ClassNotFoundException if the class was not found
- */
- public Class loadClass(String name) throws ClassNotFoundException
- {
- return loadClass(name, true);
- }
-
- /**
- * Loads the class with the specified name. The <code>loadClass</code>
- * method is called by the Java Virtual Machine when a class loaded by
- * a class loader first references another class. The default
- * implementation of <code>loadClass</code> will search for classes in
- * the following order:
- * <ol>
- * <li> Call <code>findLoadedClass</code> to check if the class has
- * already been loaded.
- * <p>
- * <li> Call the <code>loadClass</code> method of the parent class
- * loader to load the class, or <code>findSystemClass</code>
- * if no parent class loader was specified.
- * <p>
- * <li> Call the <code>findLocalClass</code> method to find the class
- * locally.
- * </ol>
- * If the class was found using the above steps, and the
- * <code>resolve</code> flag is true, this method will then call
- * the <code>resolveClass</code> method on the resulting class object.
- * <p>
- * Class loader implementations that use the new delegation model
- * introduced in 1.2 should override the <code>findLocalClass</code>
- * method rather than <code>loadClass</code>.
- *
- * @param name the name of the class
- * @param resolve if <code>true</code> then resolve the class
- * @return the resulting <code>Class</code> 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) {
- // Make sure that we are allowed to load the class
- int i = name.lastIndexOf('.');
- if (i != -1) {
- checkPackageAccess(name.substring(0, i));
- }
- try {
- if (parent != null) {
- c = parent.loadClass(name, false);
- } else {
- c = findSystemClass(name);
- }
- } catch (ClassNotFoundException e) {
- // Stop here if an error actually occurred while trying
- // to load the class.
- if (e.getException() != null) {
- throw e;
- }
- }
- if (c == null) {
- // If still not found, then call findLocalClass in order
- // to find the class locally.
- c = findLocalClass(name);
- }
- }
- if (resolve) {
- resolveClass(c);
- }
- return c;
- }
-
- /**
- * This method can be overridden to throw a <code>SecurityException</code>
- * if the calling thread is not allowed to access the package specified
- * by the argument. By default, the calling thread is allowed to access
- * any package.
- * <p>
- * For example, in order to perform this check using the current
- * <code>SecurityManager</code>:
- * <pre>
- * SecurityManager sm = System.getSecurityManager();
- * if (sm != null) {
- * sm.checkPackageAccess(name.substring(0, i));
- * }
- * </pre>
- *
- * @param name the package name
- * @exception SecurityException if the caller cannot access the specified
- * package
- * @since JDK1.2
- */
- protected void checkPackageAccess(String name) throws SecurityException {
- }
-
- /**
- * Finds the specified class locally. This method should be overridden
- * by class loader implementations that follow the new delegation model
- * for loading classes, and will be called by the <code>loadClass</code>
- * method after checking the parent class loader for the requested class.
- * The default implementation throws <code>ClassNotFoundException</code>.
- *
- * @param name the name of the class
- * @return the resulting <code>Class</code> object
- * @exception ClassNotFoundException if the class could not be found
- * @since JDK1.2
- */
- protected Class findLocalClass(String name) throws ClassNotFoundException {
- throw new ClassNotFoundException(name);
- }
-
- /**
- * Converts an array of bytes into an instance of class
- * <code>Class</code>. 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
- * @param off the start offset of the class data
- * @param len the length of the class data
- * @return the <code>Class</code> object that was created from the
- * specified class data
- * @exception ClassFormatError if the data did not contain a valid class
- * @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 ClassFormatError
- {
- return defineClass(null, b, off, len);
- }
-
- /**
- * Converts an array of bytes into an instance of class <code>Class</code>.
- * Before the Class can be used it must be resolved.
- * <p>
- * This method assigns a default <code>ProtectionDomain</code> to
- * the newly defined class. The <code>ProtectionDomain</code>
- * contains the set of permissions granted when
- * a call to <code>Policy.getPolicy().evaluate()</code> is made with a
- * Codesource of <code>null,null</code>. The default domain is
- * created on the first invocation of <code>defineClass</code>, and
- * re-used on subsequent calls.
- * <p>
- * Note: There is a similar <code>defineClass</code> method in
- * <code>java.security.SecureClassLoader</code> (a ClassLoader
- * subclass) that assigns the new class to a passed-in
- * <code>ProtectionDomain</code>. Also, a class can be assigned to
- * a new <code>ProtectionDomain</code> (one with different permissions)
- * by a call to the <code>java.lang.Class setProtectionDomain</code>
- * method, if the caller has permission to
- * reset the domain.
- *
- * @param name the expected name of the class, or <code>null</code>
- * 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
- * @param off the start offset of the class data
- * @param len the length of the class data
- * @return the <code>Class</code> object that was created from the
- * specified class data
- * @exception ClassFormatError if the data did not contain a valid class
- * @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 ClassFormatError
- {
- check();
- Class c = defineClass0(name, b, off, len);
- if (c != null) {
- classes.put(c.getName(), c);
- c.setProtectionDomain0(getDefaultDomain());
- }
- return c;
- }
-
- /**
- * Resolves the class so that an instance of the class can be created,
- * or so that one of its methods can be called. This method will be
- * called by <code>loadClass</code> if the resolve flag is
- * <code>true</code>.
- *
- * @param c the class to be resolved
- * @see java.lang.ClassLoader#defineClass(java.lang.String,byte[],int,int)
- */
- protected final void resolveClass(Class c) {
- check();
- resolveClass0(c);
- }
-
- /**
- * Finds the system class with the specified name, loading it in if
- * necessary.
- * <p>
- * A system class is a class loaded from the local file system in a
- * platform-dependent manner, and has no associated class loader.
- *
- * @param name the name of the system class
- * @return a system class with the given name
- * @exception ClassNotFoundException if the class could not be found
- */
- protected final Class findSystemClass(String name)
- throws ClassNotFoundException
- {
- check();
- return findSystemClass0(name);
- }
-
- /**
- * Returns the parent class loader for delegation, or <code>null</code>
- * if none, in which case <code>ClassLoader</code> will delegate to the
- * system class loader.
- *
- * @exception SecurityException if the caller does not have
- * <code>RuntimePermission("getClassLoader")</code> permission
- * @since JDK1.2
- */
- public ClassLoader getParent() {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null) {
- sm.checkPermission(getClassLoaderPerm);
- }
- return parent;
- }
-
- /**
- * Sets the signers of a class. This should be called after defining a
- * class.
- * @param c the <code>Class</code> object
- * @param signers the signers for the class
- * @since JDK1.1
- */
- protected final void setSigners(Class c, Object[] signers) {
- check();
- c.setSigners(signers);
- }
-
- private native Class defineClass0(String name, byte[] b, int off, int len);
- private native void resolveClass0(Class c);
- private native Class findSystemClass0(String name)
- throws ClassNotFoundException;
-
- /*
- * Check to make sure the class loader has been initialized.
- */
- private void check() {
- if (!initialized) {
- throw new SecurityException("ClassLoader object not initialized");
- }
- }
-
- /**
- * Finds the class with the given name if it had been previously loaded
- * through this class loader.
- *
- * @param name the class name
- * @return the <code>Class</object> object, or <code>null</code> if
- * the class has not been loaded
- * @since JDK1.1
- */
- protected final Class findLoadedClass(String name) {
- return (Class)classes.get(name);
- }
-
- /*
- * Called directly by the Virtual Machine to load and resolve a class.
- */
- final Class loadClassInternal(String name, boolean resolve)
- throws ClassNotFoundException
- {
- name = name.replace('/', '.');
- Class c = (Class)classes.get(name);
- if (c == null) {
- c = loadClass(name, false);
- if (c == null) {
- throw new ClassNotFoundException(name);
- }
- // Is the following still necessary now that defineClass
- // also performs the same check?
- if (!name.equals(c.getName())) {
- throw new ClassNotFoundException(name);
- }
- classes.put(name, c);
- }
- if (resolve) {
- resolveClass(c);
- }
- return c;
- }
-
- /**
- * 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.
- * <p>
- * The name of a resource is a "/"-separated path name that identifies
- * the resource.
- * <p>
- * This method will first search the parent class loader for the
- * resource, then call <code>getLocalResource</code> to find the
- * resource locally.
- *
- * @param name resource name
- * @return a URL for reading the resource, or <code>null</code> if
- * the resource could not be found or the caller doesn't have
- * adequate privileges to get the resource.
- * @since JDK1.1
- * @see #getLocalResource
- */
- public URL getResource(String name) {
- URL url;
- if (parent != null) {
- url = parent.getResource(name);
- } else {
- url = getSystemResource(name);
- }
- if (url == null) {
- url = getLocalResource(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.
- * <p>
- * The name of a resource is a "/"-separated path name that identifies
- * the resource.
- * <p>
- * This method will first search the parent class loader for the
- * resource, then call <code>getLocalResource</code> to find the
- * resource locally.
- *
- * @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.
- * @since JDK1.2
- * @see #getResource
- * @see #getLocalResources
- */
- public final Enumeration getResources(String name) throws IOException {
- Enumeration[] tmp = new Enumeration[2];
- if (parent != null) {
- tmp[0] = parent.getResources(name);
- } else {
- tmp[0] = getSystemResources(name);
- }
- tmp[1] = getLocalResources(name);
-
- return new CompoundEnumeration(tmp);
- }
-
- /**
- * Returns an Enumeration of URLs representing all the local resources
- * with the given name. Class loader implementations should override this
- * method to load resources from a local source.
- *
- * @param name the resource name
- * @return an Enumeration of URLs for the local resources
- * @since JDK1.2
- */
- public Enumeration getLocalResources(String name) throws IOException {
- return new CompoundEnumeration(new Enumeration[0]);
- }
-
- /**
- * Finds the local resource with the given name. Class loader
- * implementations should override this method to load a resource
- * from a local source.
- *
- * @param name the resource name
- * @return a URL for reading the resource, or <code>null</code>
- * if the resource could not be found
- * @since JDK1.2
- */
- public URL getLocalResource(String name) {
- return null;
- }
-
- /**
- * Finds the system resource with the given name. System resources
- * are those loaded from the system class path.
- *
- * @param name the resource name
- * @return a URL for reading the resource, or <code>null</code> if
- * the resource could not be found
- * @since JDK1.1
- */
- public static URL getSystemResource(String name) {
- try {
- AccessController.beginPrivileged();
- URLClassPath ucp = getSystemClassPath();
- Resource res = ucp.getResource(name);
- return res != null ? res.getURL() : null;
- } finally {
- AccessController.endPrivileged();
- }
- }
-
- /**
- * Returns an enumeration of URLs specifying all of the system
- * resources with the specified name. System resources are those
- * loaded from the system class path.
- *
- * @param name the resource name
- * @return an enumeration of resource URLs
- * @since JDK1.2
- */
- public static Enumeration getSystemResources(String name) {
- try {
- AccessController.beginPrivileged();
- final Enumeration e = getSystemClassPath().getResources(name);
- return new Enumeration () {
- public Object nextElement() {
- return ((Resource)e.nextElement()).getURL();
- }
- public boolean hasMoreElements() {
- return e.hasMoreElements();
- }
- };
- } finally {
- AccessController.endPrivileged();
- }
- }
-
- /*
- * Returns the URLClassPath that is used for finding system resources.
- */
- static URLClassPath getSystemClassPath() {
- if (systemClassPath == null) {
- URL[] urls;
- String prop = System.getProperty("java.sys.class.path");
- if (prop == null) {
- // We are running with the old-style launcher, so use
- // java.class.path instead.
- prop = System.getProperty("java.class.path");
- }
- if (prop != null) {
- urls = java.net.URLClassLoader.pathToURLs(prop);
- } else {
- urls = new URL[0];
- }
- systemClassPath = new URLClassPath(urls);
- }
- return systemClassPath;
- }
-
- private static URLClassPath systemClassPath;
-
- /**
- * Returns an input stream for reading the specified resource.
- *
- * @param name the resource name
- * @return an input stream for reading the resource, or <code>null</code>
- * 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;
- }
- }
-
- /**
- * Returns an input stream for reading the specified system resource.
- * System resources are those loaded from the system class path.
- *
- * @param name the resource name
- * @return an input stream for reading the resource, or <code>null</code>
- * 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 base class loader for delegation. This is the default
- * delegation parent for new <code>ClassLoader</code> instances, and
- * is usually the <code>ClassLoader</code> that was used to start the
- * application.
- *
- * @return the base <code>ClassLoader</code> for delegation, or
- * <code>null</code> if none
- * @exception SecurityException if the caller does not have
- * <code>RuntimePermission("getClassLoader")</code> permission
- * @since JDK1.2
- */
- public static ClassLoader getBaseClassLoader() {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null) {
- sm.checkPermission(getClassLoaderPerm);
- }
- if (!baseSet) {
- Launcher l = Launcher.getLauncher();
- if (l != null) {
- base = l.getClassLoader();
- }
- baseSet = true;
- }
- return base;
- }
-
- private static ClassLoader base;
- private static boolean baseSet;
-
- private static final RuntimePermission getClassLoaderPerm =
- new RuntimePermission("getClassLoader");
-
- /**
- * 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 specified, then this package is sealed with
- * respect to the given base URL
- * @exception IllegalArgumentException
- * if package name duplicates and existing package either in
- * this class loader or the parent class loader
- */
- protected Package definePackage(String name, String specTitle,
- String specVersion, String specVendor,
- String implTitle, String implVersion,
- String implVendor, URL sealBase)
- throws IllegalArgumentException
- {
- Package pkg = getPackage(name);
- if (pkg != null) {
- throw new IllegalArgumentException(name);
- }
- pkg = new Package(name, specTitle, specVersion, specVendor,
- implTitle, implVersion, implVendor,
- sealBase);
- packages.put(name, pkg);
- return pkg;
- }
-
- /**
- * Returns the Package defined in this ClassLoader for the given name.
- *
- * @param name the package name
- * @return the Package corresponding to the given name, or null if not
- * found
- */
- protected Package getPackage(String name) {
- Package pkg = (Package)packages.get(name);
- if (pkg != null) {
- return pkg;
- } else if (parent != null) {
- return parent.getPackage(name);
- } else {
- return Package.getSystemPackage(name);
- }
- }
-
- /**
- * Returns all of the Packages defined in this ClassLoader.
- */
- protected Package[] getPackages() {
- Hashtable ptab = (Hashtable)packages.clone();
- Package[] pkgs;
- if (parent != null) {
- pkgs = parent.getPackages();
- } else {
- pkgs = Package.getSystemPackages();
- }
- if (pkgs != null) {
- for (int i = 0; i < pkgs.length; i++) {
- ptab.put(pkgs[i].getName(), pkgs[i]);
- }
- }
- Enumeration e = ptab.elements();
- pkgs = new Package[ptab.size()];
- for (int i = 0; i < pkgs.length; i++) {
- pkgs[i] = (Package)e.nextElement();
- }
- return pkgs;
- }
-
- /**
- * The inner class NativeLibrary denotes a loaded native library
- * instance. Every classloader contains a vector of loaded native
- * libraries in the private field <code>nativeLibraries</code>.
- * The native libraries loaded into the system are entered into
- * the <code>systemNativeLibraries</code> 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.91, 03/18/98
- * @see java.lang.ClassLoader
- * @since JDK1.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 loader this native library belongs. */
- private ClassLoader loader;
- /* the canonicalized name of the native library. */
- String name;
- /* a list of objects the native library keeps reference to. */
- private Vector objects;
-
- native void load(String name);
- native long find(String name);
- native void unload();
-
- public NativeLibrary(ClassLoader loader, String name) {
- this.name = name;
- this.loader = loader;
- objects = new Vector();
- }
-
- protected void finalize() {
- synchronized (loadedLibraryNames) {
- if (handle != 0) {
- /* remove the native library name */
- int size = loadedLibraryNames.size();
- for (int i = 0; i < size; i++) {
- if (name.equals(loadedLibraryNames.elementAt(i))) {
- loadedLibraryNames.removeElementAt(i);
- break;
- }
- }
- /* unload the library. */
- unload();
- }
- }
- }
-
- /**
- * This method registers an object with the native library, so that
- * the object does not get collected until the native library can be
- * unloaded.
- *
- * This is usually called in the native methods, where the
- * field and method IDs are computed and cached. By registering the
- * class objcts with the native library, the field and method IDs
- * remain valid until the native library is unloaded.
- *
- * @param obj the objected to be registered with the native library.
- * @since JDK1.2
- */
- public void registerObject(Object obj) {
- objects.addElement(obj);
- }
- }
-
- /* the "default" domain. Set as the default ProtectionDomain
- * on newly created classses.
- */
- private ProtectionDomain defaultDomain = null;
-
- /*
- * returns (and initializes) the default domain.
- */
-
- private ProtectionDomain getDefaultDomain() {
- if (defaultDomain == null) {
- synchronized(ClassLoader.class) {
- if (defaultDomain == null) {
- CodeSource cs = new CodeSource(null, null);
- try {
- java.security.AccessController.beginPrivileged();
- defaultDomain = new ProtectionDomain(cs,
- Policy.getPolicy().evaluate(cs));
- } finally {
- java.security.AccessController.endPrivileged();
- }
- }
- }
- }
- return defaultDomain;
- }
-
- /* All native library names we've loaded. */
- private static Vector loadedLibraryNames = new Vector();
- /* Native libraries belonging to system classes. */
- private static Vector systemNativeLibraries = new Vector();
- /* Native libraries associated with the class loader. */
- private Vector nativeLibraries = new Vector();
-
- /* native libraries being loaded. */
- private static Stack librariesBeingLoaded = new Stack();
-
- /* Called in the java.lang.Runtime class to implement load
- * and loadLibrary.
- *
- * returns true on success, false on failure.
- */
- static boolean loadLibrary(ClassLoader loader, String name) {
- Vector libs =
- loader != null ? loader.nativeLibraries : systemNativeLibraries;
- synchronized (libs) {
- int size = libs.size();
- for (int i = 0; i < size; i++) {
- NativeLibrary lib = (NativeLibrary)libs.elementAt(i);
- if (name.equals(lib.name)) {
- return true;
- }
- }
-
- synchronized (loadedLibraryNames) {
- if (loadedLibraryNames.contains(name)) {
- throw new UnsatisfiedLinkError
- ("Native Library " +
- name +
- " already loaded in another classloader");
- }
- /* If the library is being loaded (must be by
- * the same thread, because Runtime.load and
- * Runtime.loadLibrary are synchronous). The
- * reason is can occur is that the JNI_OnLoad
- * function can cause another loadLibrary call.
- *
- * Thus we can use a static stack to hold the list
- * of libraries we are loading.
- *
- * If there is a pending load operation for the
- * library, we immediately return success; otherwise,
- * we raise UnsatisfiedLinkError.
- */
- int n = librariesBeingLoaded.size();
- for (int i = 0; i < n; i++) {
- NativeLibrary lib = (NativeLibrary)
- librariesBeingLoaded.elementAt(i);
- if (name.equals(lib.name)) {
- if (loader == lib.loader) {
- return true;
- } else {
- throw new UnsatisfiedLinkError
- ("Native Library " +
- name +
- " is being loaded in another classloader");
- }
- }
- }
- NativeLibrary lib = new NativeLibrary(loader, name);
- librariesBeingLoaded.push(lib);
- try {
- lib.load(name);
- if (lib.handle != 0) {
- loadedLibraryNames.addElement(name);
- libs.addElement(lib);
- return true;
- } else {
- return false;
- }
- } finally {
- librariesBeingLoaded.pop();
- }
- }
- }
- }
-
- /* Called in the VM class linking code. */
- static long findNative(ClassLoader loader, String name) {
- Vector libs =
- loader != null ? loader.nativeLibraries : systemNativeLibraries;
- synchronized (libs) {
- int size = libs.size();
- for (int i = 0; i < size; i++) {
- NativeLibrary lib = (NativeLibrary)libs.elementAt(i);
- long entry = lib.find(name);
- if (entry != 0)
- return entry;
- }
- }
- return 0;
- }
- }
-