12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145 |
- /* ClassLoader.java -- responsible for loading classes into the VM
- Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
- This file is part of GNU Classpath.
- GNU Classpath is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
- GNU Classpath 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 for more details.
- You should have received a copy of the GNU General Public License
- along with GNU Classpath; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301 USA.
- Linking this library statically or dynamically with other modules is
- making a combined work based on this library. Thus, the terms and
- conditions of the GNU General Public License cover the whole
- combination.
- As a special exception, the copyright holders of this library give you
- permission to link this library with independent modules to produce an
- executable, regardless of the license terms of these independent
- modules, and to copy and distribute the resulting executable under
- terms of your choice, provided that you also meet, for each linked
- independent module, the terms and conditions of the license of that
- module. An independent module is a module which is not derived from
- or based on this library. If you modify this library, you may extend
- this exception to your version of the library, but you are not
- obligated to do so. If you do not wish to do so, delete this
- exception statement from your version. */
- package java.lang;
- import gnu.classpath.SystemProperties;
- import gnu.classpath.VMStackWalker;
- import gnu.java.util.DoubleEnumeration;
- import gnu.java.util.EmptyEnumeration;
- import java.io.IOException;
- import java.io.InputStream;
- import java.lang.ref.WeakReference;
- import java.net.URL;
- import java.nio.ByteBuffer;
- import java.security.CodeSource;
- import java.security.PermissionCollection;
- import java.security.Policy;
- import java.security.ProtectionDomain;
- import java.util.Enumeration;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.concurrent.ConcurrentHashMap;
- import java.lang.annotation.Annotation;
- /**
- * The ClassLoader is a way of customizing the way Java gets its classes
- * and loads them into memory. The verifier and other standard Java things
- * still run, but the ClassLoader is allowed great flexibility in determining
- * where to get the classfiles and when to load and resolve them. For that
- * matter, a custom ClassLoader can perform on-the-fly code generation or
- * modification!
- *
- * <p>Every classloader has a parent classloader that is consulted before
- * the 'child' classloader when classes or resources should be loaded.
- * This is done to make sure that classes can be loaded from an hierarchy of
- * multiple classloaders and classloaders do not accidentially redefine
- * already loaded classes by classloaders higher in the hierarchy.
- *
- * <p>The grandparent of all classloaders is the bootstrap classloader, which
- * loads all the standard system classes as implemented by GNU Classpath. The
- * other special classloader is the system classloader (also called
- * application classloader) that loads all classes from the CLASSPATH
- * (<code>java.class.path</code> system property). The system classloader
- * is responsible for finding the application classes from the classpath,
- * and delegates all requests for the standard library classes to its parent
- * the bootstrap classloader. Most programs will load all their classes
- * through the system classloaders.
- *
- * <p>The bootstrap classloader in GNU Classpath is implemented as a couple of
- * static (native) methods on the package private class
- * <code>java.lang.VMClassLoader</code>, the system classloader is an
- * instance of <code>gnu.java.lang.SystemClassLoader</code>
- * (which is a subclass of <code>java.net.URLClassLoader</code>).
- *
- * <p>Users of a <code>ClassLoader</code> will normally just use the methods
- * <ul>
- * <li> <code>loadClass()</code> to load a class.</li>
- * <li> <code>getResource()</code> or <code>getResourceAsStream()</code>
- * to access a resource.</li>
- * <li> <code>getResources()</code> to get an Enumeration of URLs to all
- * the resources provided by the classloader and its parents with the
- * same name.</li>
- * </ul>
- *
- * <p>Subclasses should implement the methods
- * <ul>
- * <li> <code>findClass()</code> which is called by <code>loadClass()</code>
- * when the parent classloader cannot provide a named class.</li>
- * <li> <code>findResource()</code> which is called by
- * <code>getResource()</code> when the parent classloader cannot provide
- * a named resource.</li>
- * <li> <code>findResources()</code> which is called by
- * <code>getResource()</code> to combine all the resources with the
- * same name from the classloader and its parents.</li>
- * <li> <code>findLibrary()</code> which is called by
- * <code>Runtime.loadLibrary()</code> when a class defined by the
- * classloader wants to load a native library.</li>
- * </ul>
- *
- * @author John Keiser
- * @author Mark Wielaard
- * @author Eric Blake (ebb9@email.byu.edu)
- * @see Class
- * @since 1.0
- */
- public abstract class ClassLoader
- {
- /**
- * All classes loaded by this classloader. VM's may choose to implement
- * this cache natively; but it is here available for use if necessary. It
- * is not private in order to allow native code (and trusted subclasses)
- * access to this field.
- */
- final HashMap loadedClasses = new HashMap();
- /**
- * Loading constraints registered with this classloader. This maps
- * a class name to a weak reference to a class. When the reference
- * is non-null, it means that a reference to the name must resolve
- * to the indicated class.
- */
- final HashMap<String, WeakReference<Class>> loadingConstraints
- = new HashMap<String, WeakReference<Class>>();
- /**
- * All packages defined by this classloader. It is not private in order to
- * allow native code (and trusted subclasses) access to this field.
- */
- final HashMap definedPackages = new HashMap();
- /**
- * The classloader that is consulted before this classloader.
- * If null then the parent is the bootstrap classloader.
- */
- private final ClassLoader parent;
- /**
- * This is true if this classloader was successfully initialized.
- * This flag is needed to avoid a class loader attack: even if the
- * security manager rejects an attempt to create a class loader, the
- * malicious class could have a finalize method which proceeds to
- * define classes.
- */
- private final boolean initialized;
- /**
- * System/Application classloader: defaults to an instance of
- * gnu.java.lang.SystemClassLoader, unless the first invocation of
- * getSystemClassLoader loads another class loader because of the
- * java.system.class.loader property. The initialization of this field
- * is somewhat circular - getSystemClassLoader() checks whether this
- * field is null in order to bypass a security check.
- */
- static final ClassLoader systemClassLoader =
- VMClassLoader.getSystemClassLoader();
- /**
- * This cache maps from a Class to its associated annotations. It's
- * declared here so that when this class loader becomes unreachable,
- * so will the corresponding cache.
- */
- private final ConcurrentHashMap<AnnotationsKey,Object[]>
- declaredAnnotations
- = new ConcurrentHashMap<AnnotationsKey,Object[]>();
-
- static final class AnnotationsKey
- {
- final int /* jv_attr_type */ member_type;
- final int member_index;
- final int /* jv_attr_kind */ kind_req;
- final Class declaringClass;
- final int hashCode;
- public AnnotationsKey (Class declaringClass,
- int member_type,
- int member_index,
- int kind_req)
- {
- this.member_type = member_type;
- this.member_index = member_index;
- this.kind_req = kind_req;
- this.declaringClass = declaringClass;
- hashCode = (member_type ^ member_index ^ kind_req
- ^ declaringClass.hashCode());
- }
- public boolean equals(Object obj)
- {
- AnnotationsKey other = (AnnotationsKey)obj;
- return (this.member_type == other.member_type
- && this.member_index == other.member_index
- && this.kind_req == other.kind_req
- && this.declaringClass == other.declaringClass);
- }
- public int hashCode()
- {
- return hashCode;
- }
- public static final Annotation[] NIL = new Annotation[0];
- }
-
- final Object[] getDeclaredAnnotations(Class declaringClass,
- int member_type,
- int member_index,
- int kind_req)
- {
- Object[] result
- = declaredAnnotations.get (new AnnotationsKey
- (declaringClass,
- member_type,
- member_index,
- kind_req));
- if (result != AnnotationsKey.NIL && result != null)
- return (Object[])result.clone();
- return null;
- }
- final Object[] putDeclaredAnnotations(Class declaringClass,
- int member_type,
- int member_index,
- int kind_req,
- Object[] annotations)
- {
- declaredAnnotations.put
- (new AnnotationsKey
- (declaringClass, member_type,
- member_index, kind_req),
- annotations == null ? AnnotationsKey.NIL : annotations);
- return annotations == null ? null : (Object[])annotations.clone();
- }
- static
- {
- // Find out if we have to install a default security manager. Note
- // that this is done here because we potentially need the system
- // class loader to load the security manager and note also that we
- // don't need the security manager until the system class loader
- // is created. If the runtime chooses to use a class loader that
- // doesn't have the system class loader as its parent, it is
- // responsible for setting up a security manager before doing so.
- String secman = SystemProperties.getProperty("java.security.manager");
- if (secman != null && SecurityManager.current == null)
- {
- if (secman.equals("") || secman.equals("default"))
- {
- SecurityManager.current = new SecurityManager();
- }
- else
- {
- try
- {
- Class cl = Class.forName(secman, false, systemClassLoader);
- SecurityManager.current = (SecurityManager) cl.newInstance();
- }
- catch (Exception x)
- {
- throw (InternalError)
- new InternalError("Unable to create SecurityManager")
- .initCause(x);
- }
- }
- }
- }
- /**
- * The default protection domain, used when defining a class with a null
- * paramter for the domain.
- */
- static final ProtectionDomain defaultProtectionDomain;
- static
- {
- CodeSource cs = new CodeSource(null, null);
- PermissionCollection perm = Policy.getPolicy().getPermissions(cs);
- defaultProtectionDomain = new ProtectionDomain(cs, perm);
- }
- /**
- * The desired assertion status of classes loaded by this loader, if not
- * overridden by package or class instructions.
- */
- // Package visible for use by Class.
- boolean defaultAssertionStatus = VMClassLoader.defaultAssertionStatus();
- /**
- * The command-line state of the package assertion status overrides. This
- * map is never modified, so it does not need to be synchronized.
- */
- // Package visible for use by Class.
- static final Map systemPackageAssertionStatus
- = VMClassLoader.packageAssertionStatus();
- /**
- * The map of package assertion status overrides, or null if no package
- * overrides have been specified yet. The values of the map should be
- * Boolean.TRUE or Boolean.FALSE, and the unnamed package is represented
- * by the null key. This map must be synchronized on this instance.
- */
- // Package visible for use by Class.
- Map packageAssertionStatus;
- /**
- * The command-line state of the class assertion status overrides. This
- * map is never modified, so it does not need to be synchronized.
- */
- // Package visible for use by Class.
- static final Map systemClassAssertionStatus
- = VMClassLoader.classAssertionStatus();
- /**
- * The map of class assertion status overrides, or null if no class
- * overrides have been specified yet. The values of the map should be
- * Boolean.TRUE or Boolean.FALSE. This map must be synchronized on this
- * instance.
- */
- // Package visible for use by Class.
- Map classAssertionStatus;
- /**
- * Create a new ClassLoader with as parent the system classloader. There
- * may be a security check for <code>checkCreateClassLoader</code>.
- *
- * @throws SecurityException if the security check fails
- */
- protected ClassLoader() throws SecurityException
- {
- this(systemClassLoader);
- }
- /**
- * Create a new ClassLoader with the specified parent. The parent will
- * be consulted when a class or resource is requested through
- * <code>loadClass()</code> or <code>getResource()</code>. Only when the
- * parent classloader cannot provide the requested class or resource the
- * <code>findClass()</code> or <code>findResource()</code> method
- * of this classloader will be called. There may be a security check for
- * <code>checkCreateClassLoader</code>.
- *
- * @param parent the classloader's parent, or null for the bootstrap
- * classloader
- * @throws SecurityException if the security check fails
- * @since 1.2
- */
- protected ClassLoader(ClassLoader parent)
- {
- // May we create a new classloader?
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- sm.checkCreateClassLoader();
- this.parent = parent;
- this.initialized = true;
- }
- /**
- * Load a class using this ClassLoader or its parent, without resolving
- * it. Calls <code>loadClass(name, false)</code>.
- *
- * <p>Subclasses should not override this method but should override
- * <code>findClass()</code> which is called by this method.</p>
- *
- * @param name the name of the class relative to this ClassLoader
- * @return the loaded class
- * @throws ClassNotFoundException if the class cannot be found
- */
- public Class<?> loadClass(String name) throws ClassNotFoundException
- {
- return loadClass(name, false);
- }
- private native Class loadClassFromSig(String name)
- throws ClassNotFoundException;
- /**
- * Load a class using this ClassLoader or its parent, possibly resolving
- * it as well using <code>resolveClass()</code>. It first tries to find
- * out if the class has already been loaded through this classloader by
- * calling <code>findLoadedClass()</code>. Then it calls
- * <code>loadClass()</code> on the parent classloader (or when there is
- * no parent it uses the VM bootclassloader). If the class is still
- * not loaded it tries to create a new class by calling
- * <code>findClass()</code>. Finally when <code>resolve</code> is
- * <code>true</code> it also calls <code>resolveClass()</code> on the
- * newly loaded class.
- *
- * <p>Subclasses should not override this method but should override
- * <code>findClass()</code> which is called by this method.</p>
- *
- * @param name the fully qualified name of the class to load
- * @param resolve whether or not to resolve the class
- * @return the loaded class
- * @throws ClassNotFoundException if the class cannot be found
- */
- protected synchronized Class<?> loadClass(String name, boolean resolve)
- throws ClassNotFoundException
- {
- SecurityManager sm = SecurityManager.current;
- if (sm != null)
- {
- int lastDot = name.lastIndexOf('.');
- if (lastDot != -1)
- sm.checkPackageAccess(name.substring(0, lastDot));
- }
- // Arrays are handled specially.
- Class c;
- if (name.length() > 0 && name.charAt(0) == '[')
- c = loadClassFromSig(name);
- else
- {
- // Have we already loaded this class?
- c = findLoadedClass(name);
- if (c == null)
- {
- // Can the class be loaded by a parent?
- try
- {
- if (parent == null)
- {
- c = VMClassLoader.loadClass(name, resolve);
- if (c != null)
- return c;
- }
- else
- {
- return parent.loadClass(name, resolve);
- }
- }
- catch (ClassNotFoundException e)
- {
- }
- // Still not found, we have to do it ourself.
- c = findClass(name);
- }
- }
- if (resolve)
- resolveClass(c);
- return c;
- }
- /**
- * Called for every class name that is needed but has not yet been
- * defined by this classloader or one of its parents. It is called by
- * <code>loadClass()</code> after both <code>findLoadedClass()</code> and
- * <code>parent.loadClass()</code> couldn't provide the requested class.
- *
- * <p>The default implementation throws a
- * <code>ClassNotFoundException</code>. Subclasses should override this
- * method. An implementation of this method in a subclass should get the
- * class bytes of the class (if it can find them), if the package of the
- * requested class doesn't exist it should define the package and finally
- * it should call define the actual class. It does not have to resolve the
- * class. It should look something like the following:<br>
- *
- * <pre>
- * // Get the bytes that describe the requested class
- * byte[] classBytes = classLoaderSpecificWayToFindClassBytes(name);
- * // Get the package name
- * int lastDot = name.lastIndexOf('.');
- * if (lastDot != -1)
- * {
- * String packageName = name.substring(0, lastDot);
- * // Look if the package already exists
- * if (getPackage(packageName) == null)
- * {
- * // define the package
- * definePackage(packageName, ...);
- * }
- * }
- * // Define and return the class
- * return defineClass(name, classBytes, 0, classBytes.length);
- * </pre>
- *
- * <p><code>loadClass()</code> makes sure that the <code>Class</code>
- * returned by <code>findClass()</code> will later be returned by
- * <code>findLoadedClass()</code> when the same class name is requested.
- *
- * @param name class name to find (including the package name)
- * @return the requested Class
- * @throws ClassNotFoundException when the class can not be found
- * @since 1.2
- */
- protected Class<?> findClass(String name) throws ClassNotFoundException
- {
- throw new ClassNotFoundException(name);
- }
- /**
- * Helper to define a class using a string of bytes. This version is not
- * secure.
- *
- * @param data the data representing the classfile, in classfile format
- * @param offset the offset into the data where the classfile starts
- * @param len the length of the classfile data in the array
- * @return the class that was defined
- * @throws ClassFormatError if data is not in proper classfile format
- * @throws IndexOutOfBoundsException if offset or len is negative, or
- * offset + len exceeds data
- * @deprecated use {@link #defineClass(String, byte[], int, int)} instead
- */
- protected final Class<?> defineClass(byte[] data, int offset, int len)
- throws ClassFormatError
- {
- return defineClass(null, data, offset, len);
- }
- /**
- * Helper to define a class using a string of bytes without a
- * ProtectionDomain. Subclasses should call this method from their
- * <code>findClass()</code> implementation. The name should use '.'
- * separators, and discard the trailing ".class". The default protection
- * domain has the permissions of
- * <code>Policy.getPolicy().getPermissions(new CodeSource(null, null))</code>.
- *
- * @param name the name to give the class, or null if unknown
- * @param data the data representing the classfile, in classfile format
- * @param offset the offset into the data where the classfile starts
- * @param len the length of the classfile data in the array
- * @return the class that was defined
- * @throws ClassFormatError if data is not in proper classfile format
- * @throws IndexOutOfBoundsException if offset or len is negative, or
- * offset + len exceeds data
- * @throws SecurityException if name starts with "java."
- * @since 1.1
- */
- protected final Class<?> defineClass(String name, byte[] data, int offset,
- int len) throws ClassFormatError
- {
- return defineClass(name, data, offset, len, null);
- }
- /**
- * Helper to define a class using a string of bytes. Subclasses should call
- * this method from their <code>findClass()</code> implementation. If the
- * domain is null, the default of
- * <code>Policy.getPolicy().getPermissions(new CodeSource(null, null))</code>
- * is used. Once a class has been defined in a package, all further classes
- * in that package must have the same set of certificates or a
- * SecurityException is thrown.
- *
- * @param name the name to give the class. null if unknown
- * @param data the data representing the classfile, in classfile format
- * @param offset the offset into the data where the classfile starts
- * @param len the length of the classfile data in the array
- * @param domain the ProtectionDomain to give to the class, null for the
- * default protection domain
- * @return the class that was defined
- * @throws ClassFormatError if data is not in proper classfile format
- * @throws IndexOutOfBoundsException if offset or len is negative, or
- * offset + len exceeds data
- * @throws SecurityException if name starts with "java.", or if certificates
- * do not match up
- * @since 1.2
- */
- protected final synchronized Class<?> defineClass(String name, byte[] data,
- int offset, int len,
- ProtectionDomain domain)
- throws ClassFormatError
- {
- checkInitialized();
- if (domain == null)
- domain = defaultProtectionDomain;
-
- Class retval = VMClassLoader.defineClass(this, name, data,
- offset, len, domain);
- loadedClasses.put(retval.getName(), retval);
- return retval;
- }
- /**
- * Helper to define a class using the contents of a byte buffer. If
- * the domain is null, the default of
- * <code>Policy.getPolicy().getPermissions(new CodeSource(null,
- * null))</code> is used. Once a class has been defined in a
- * package, all further classes in that package must have the same
- * set of certificates or a SecurityException is thrown.
- *
- * @param name the name to give the class. null if unknown
- * @param buf a byte buffer containing bytes that form a class.
- * @param domain the ProtectionDomain to give to the class, null for the
- * default protection domain
- * @return the class that was defined
- * @throws ClassFormatError if data is not in proper classfile format
- * @throws NoClassDefFoundError if the supplied name is not the same as
- * the one specified by the byte buffer.
- * @throws SecurityException if name starts with "java.", or if certificates
- * do not match up
- * @since 1.5
- */
- protected final Class<?> defineClass(String name, ByteBuffer buf,
- ProtectionDomain domain)
- throws ClassFormatError
- {
- byte[] data = new byte[buf.remaining()];
- buf.get(data);
- return defineClass(name, data, 0, data.length, domain);
- }
- /**
- * Links the class, if that has not already been done. Linking basically
- * resolves all references to other classes made by this class.
- *
- * @param c the class to resolve
- * @throws NullPointerException if c is null
- * @throws LinkageError if linking fails
- */
- protected final void resolveClass(Class<?> c)
- {
- checkInitialized();
- VMClassLoader.resolveClass(c);
- }
- /**
- * Helper to find a Class using the system classloader, possibly loading it.
- * A subclass usually does not need to call this, if it correctly
- * overrides <code>findClass(String)</code>.
- *
- * @param name the name of the class to find
- * @return the found class
- * @throws ClassNotFoundException if the class cannot be found
- */
- protected final Class<?> findSystemClass(String name)
- throws ClassNotFoundException
- {
- checkInitialized();
- return Class.forName(name, false, systemClassLoader);
- }
- /**
- * Returns the parent of this classloader. If the parent of this
- * classloader is the bootstrap classloader then this method returns
- * <code>null</code>. A security check may be performed on
- * <code>RuntimePermission("getClassLoader")</code>.
- *
- * @return the parent <code>ClassLoader</code>
- * @throws SecurityException if the security check fails
- * @since 1.2
- */
- public final ClassLoader getParent()
- {
- // Check if we may return the parent classloader.
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- {
- ClassLoader cl = VMStackWalker.getCallingClassLoader();
- if (cl != null && ! cl.isAncestorOf(this))
- sm.checkPermission(new RuntimePermission("getClassLoader"));
- }
- return parent;
- }
- /**
- * Helper to set the signers of a class. This should be called after
- * defining the class.
- *
- * @param c the Class to set signers of
- * @param signers the signers to set
- * @since 1.1
- */
- protected final void setSigners(Class<?> c, Object[] signers)
- {
- checkInitialized();
- c.setSigners(signers);
- }
- /**
- * Helper to find an already-loaded class in this ClassLoader.
- *
- * @param name the name of the class to find
- * @return the found Class, or null if it is not found
- * @since 1.1
- */
- protected final synchronized Class<?> findLoadedClass(String name)
- {
- checkInitialized();
- // NOTE: If the VM is keeping its own cache, it may make sense to have
- // this method be native.
- return (Class) loadedClasses.get(name);
- }
- /**
- * Get the URL to a resource using this classloader or one of its parents.
- * First tries to get the resource by calling <code>getResource()</code>
- * on the parent classloader. If the parent classloader returns null then
- * it tries finding the resource by calling <code>findResource()</code> on
- * this classloader. The resource name should be separated by '/' for path
- * elements.
- *
- * <p>Subclasses should not override this method but should override
- * <code>findResource()</code> which is called by this method.
- *
- * @param name the name of the resource relative to this classloader
- * @return the URL to the resource or null when not found
- */
- public URL getResource(String name)
- {
- URL result;
- if (parent == null)
- result = VMClassLoader.getResource(name);
- else
- result = parent.getResource(name);
- if (result == null)
- result = findResource(name);
- return result;
- }
- /**
- * Returns an Enumeration of all resources with a given name that can
- * be found by this classloader and its parents. Certain classloaders
- * (such as the URLClassLoader when given multiple jar files) can have
- * multiple resources with the same name that come from multiple locations.
- * It can also occur that a parent classloader offers a resource with a
- * certain name and the child classloader also offers a resource with that
- * same name. <code>getResource()</code> only offers the first resource (of the
- * parent) with a given name. This method lists all resources with the
- * same name. The name should use '/' as path separators.
- *
- * <p>The Enumeration is created by first calling <code>getResources()</code>
- * on the parent classloader and then calling <code>findResources()</code>
- * on this classloader.</p>
- *
- * @param name the resource name
- * @return an enumaration of all resources found
- * @throws IOException if I/O errors occur in the process
- * @since 1.2
- * @specnote this was <code>final</code> prior to 1.5
- */
- public Enumeration<URL> getResources(String name) throws IOException
- {
- Enumeration<URL> parentResources;
- if (parent == null)
- parentResources = VMClassLoader.getResources(name);
- else
- parentResources = parent.getResources(name);
- return new DoubleEnumeration<URL>(parentResources, findResources(name));
- }
- /**
- * Called whenever all locations of a named resource are needed.
- * It is called by <code>getResources()</code> after it has called
- * <code>parent.getResources()</code>. The results are combined by
- * the <code>getResources()</code> method.
- *
- * <p>The default implementation always returns an empty Enumeration.
- * Subclasses should override it when they can provide an Enumeration of
- * URLs (possibly just one element) to the named resource.
- * The first URL of the Enumeration should be the same as the one
- * returned by <code>findResource</code>.
- *
- * @param name the name of the resource to be found
- * @return a possibly empty Enumeration of URLs to the named resource
- * @throws IOException if I/O errors occur in the process
- * @since 1.2
- */
- protected Enumeration<URL> findResources(String name) throws IOException
- {
- return new EmptyEnumeration<URL>();
- }
- /**
- * Called whenever a resource is needed that could not be provided by
- * one of the parents of this classloader. It is called by
- * <code>getResource()</code> after <code>parent.getResource()</code>
- * couldn't provide the requested resource.
- *
- * <p>The default implementation always returns null. Subclasses should
- * override this method when they can provide a way to return a URL
- * to a named resource.
- *
- * @param name the name of the resource to be found
- * @return a URL to the named resource or null when not found
- * @since 1.2
- */
- protected URL findResource(String name)
- {
- return null;
- }
- /**
- * Get the URL to a resource using the system classloader.
- *
- * @param name the name of the resource relative to the system classloader
- * @return the URL to the resource
- * @since 1.1
- */
- public static final URL getSystemResource(String name)
- {
- return systemClassLoader.getResource(name);
- }
- /**
- * Get an Enumeration of URLs to resources with a given name using the
- * the system classloader. The enumeration firsts lists the resources with
- * the given name that can be found by the bootstrap classloader followed
- * by the resources with the given name that can be found on the classpath.
- *
- * @param name the name of the resource relative to the system classloader
- * @return an Enumeration of URLs to the resources
- * @throws IOException if I/O errors occur in the process
- * @since 1.2
- */
- public static Enumeration<URL> getSystemResources(String name)
- throws IOException
- {
- return systemClassLoader.getResources(name);
- }
- /**
- * Get a resource as stream using this classloader or one of its parents.
- * First calls <code>getResource()</code> and if that returns a URL to
- * the resource then it calls and returns the InputStream given by
- * <code>URL.openStream()</code>.
- *
- * <p>Subclasses should not override this method but should override
- * <code>findResource()</code> which is called by this method.
- *
- * @param name the name of the resource relative to this classloader
- * @return an InputStream to the resource, or null
- * @since 1.1
- */
- public InputStream getResourceAsStream(String name)
- {
- try
- {
- URL url = getResource(name);
- if (url == null)
- return null;
- return url.openStream();
- }
- catch (IOException e)
- {
- return null;
- }
- }
- /**
- * Get a resource using the system classloader.
- *
- * @param name the name of the resource relative to the system classloader
- * @return an input stream for the resource, or null
- * @since 1.1
- */
- public static final InputStream getSystemResourceAsStream(String name)
- {
- try
- {
- URL url = getSystemResource(name);
- if (url == null)
- return null;
- return url.openStream();
- }
- catch (IOException e)
- {
- return null;
- }
- }
- /**
- * Returns the system classloader. The system classloader (also called
- * the application classloader) is the classloader that is used to
- * load the application classes on the classpath (given by the system
- * property <code>java.class.path</code>. This is set as the context
- * class loader for a thread. The system property
- * <code>java.system.class.loader</code>, if defined, is taken to be the
- * name of the class to use as the system class loader, which must have
- * a public constructor which takes a ClassLoader as a parent. The parent
- * class loader passed in the constructor is the default system class
- * loader.
- *
- * <p>Note that this is different from the bootstrap classloader that
- * actually loads all the real "system" classes (the bootstrap classloader
- * is the parent of the returned system classloader).
- *
- * <p>A security check will be performed for
- * <code>RuntimePermission("getClassLoader")</code> if the calling class
- * is not a parent of the system class loader.
- *
- * @return the system class loader
- * @throws SecurityException if the security check fails
- * @throws IllegalStateException if this is called recursively
- * @throws Error if <code>java.system.class.loader</code> fails to load
- * @since 1.2
- */
- public static ClassLoader getSystemClassLoader()
- {
- // Check if we may return the system classloader
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- {
- ClassLoader cl = VMStackWalker.getCallingClassLoader();
- if (cl != null && cl != systemClassLoader)
- sm.checkPermission(new RuntimePermission("getClassLoader"));
- }
- return systemClassLoader;
- }
- /**
- * Defines a new package and creates a Package object. The package should
- * be defined before any class in the package is defined with
- * <code>defineClass()</code>. The package should not yet be defined
- * before in this classloader or in one of its parents (which means that
- * <code>getPackage()</code> should return <code>null</code>). All
- * parameters except the <code>name</code> of the package may be
- * <code>null</code>.
- *
- * <p>Subclasses should call this method from their <code>findClass()</code>
- * implementation before calling <code>defineClass()</code> on a Class
- * in a not yet defined Package (which can be checked by calling
- * <code>getPackage()</code>).
- *
- * @param name the name of the Package
- * @param specTitle the name of the specification
- * @param specVendor the name of the specification designer
- * @param specVersion the version of this specification
- * @param implTitle the name of the implementation
- * @param implVendor the vendor that wrote this implementation
- * @param implVersion the version of this implementation
- * @param sealed if sealed the origin of the package classes
- * @return the Package object for the specified package
- * @throws IllegalArgumentException if the package name is null or it
- * was already defined by this classloader or one of its parents
- * @see Package
- * @since 1.2
- */
- protected Package definePackage(String name, String specTitle,
- String specVendor, String specVersion,
- String implTitle, String implVendor,
- String implVersion, URL sealed)
- {
- if (getPackage(name) != null)
- throw new IllegalArgumentException("Package " + name
- + " already defined");
- Package p = new Package(name, specTitle, specVendor, specVersion,
- implTitle, implVendor, implVersion, sealed, this);
- synchronized (definedPackages)
- {
- definedPackages.put(name, p);
- }
- return p;
- }
- /**
- * Returns the Package object for the requested package name. It returns
- * null when the package is not defined by this classloader or one of its
- * parents.
- *
- * @param name the package name to find
- * @return the package, if defined
- * @since 1.2
- */
- protected Package getPackage(String name)
- {
- Package p;
- if (parent == null)
- p = VMClassLoader.getPackage(name);
- else
- p = parent.getPackage(name);
- if (p == null)
- {
- synchronized (definedPackages)
- {
- p = (Package) definedPackages.get(name);
- }
- }
- return p;
- }
- /**
- * Returns all Package objects defined by this classloader and its parents.
- *
- * @return an array of all defined packages
- * @since 1.2
- */
- protected Package[] getPackages()
- {
- // Get all our packages.
- Package[] packages;
- synchronized(definedPackages)
- {
- packages = new Package[definedPackages.size()];
- definedPackages.values().toArray(packages);
- }
- // If we have a parent get all packages defined by our parents.
- Package[] parentPackages;
- if (parent == null)
- parentPackages = VMClassLoader.getPackages();
- else
- parentPackages = parent.getPackages();
- Package[] allPackages = new Package[parentPackages.length
- + packages.length];
- System.arraycopy(parentPackages, 0, allPackages, 0,
- parentPackages.length);
- System.arraycopy(packages, 0, allPackages, parentPackages.length,
- packages.length);
- return allPackages;
- }
- /**
- * Called by <code>Runtime.loadLibrary()</code> to get an absolute path
- * to a (system specific) library that was requested by a class loaded
- * by this classloader. The default implementation returns
- * <code>null</code>. It should be implemented by subclasses when they
- * have a way to find the absolute path to a library. If this method
- * returns null the library is searched for in the default locations
- * (the directories listed in the <code>java.library.path</code> system
- * property).
- *
- * @param name the (system specific) name of the requested library
- * @return the full pathname to the requested library, or null
- * @see Runtime#loadLibrary(String)
- * @since 1.2
- */
- protected String findLibrary(String name)
- {
- return null;
- }
- /**
- * Set the default assertion status for classes loaded by this classloader,
- * used unless overridden by a package or class request.
- *
- * @param enabled true to set the default to enabled
- * @see #setClassAssertionStatus(String, boolean)
- * @see #setPackageAssertionStatus(String, boolean)
- * @see #clearAssertionStatus()
- * @since 1.4
- */
- public void setDefaultAssertionStatus(boolean enabled)
- {
- defaultAssertionStatus = enabled;
- }
-
- /**
- * Set the default assertion status for packages, used unless overridden
- * by a class request. This default also covers subpackages, unless they
- * are also specified. The unnamed package should use null for the name.
- *
- * @param name the package (and subpackages) to affect
- * @param enabled true to set the default to enabled
- * @see #setDefaultAssertionStatus(boolean)
- * @see #setClassAssertionStatus(String, boolean)
- * @see #clearAssertionStatus()
- * @since 1.4
- */
- public synchronized void setPackageAssertionStatus(String name,
- boolean enabled)
- {
- if (packageAssertionStatus == null)
- packageAssertionStatus
- = new HashMap(systemPackageAssertionStatus);
- packageAssertionStatus.put(name, Boolean.valueOf(enabled));
- }
-
- /**
- * Set the default assertion status for a class. This only affects the
- * status of top-level classes, any other string is harmless.
- *
- * @param name the class to affect
- * @param enabled true to set the default to enabled
- * @throws NullPointerException if name is null
- * @see #setDefaultAssertionStatus(boolean)
- * @see #setPackageAssertionStatus(String, boolean)
- * @see #clearAssertionStatus()
- * @since 1.4
- */
- public synchronized void setClassAssertionStatus(String name,
- boolean enabled)
- {
- if (classAssertionStatus == null)
- classAssertionStatus = new HashMap(systemClassAssertionStatus);
- // The toString() hack catches null, as required.
- classAssertionStatus.put(name.toString(), Boolean.valueOf(enabled));
- }
-
- /**
- * Resets the default assertion status of this classloader, its packages
- * and classes, all to false. This allows overriding defaults inherited
- * from the command line.
- *
- * @see #setDefaultAssertionStatus(boolean)
- * @see #setClassAssertionStatus(String, boolean)
- * @see #setPackageAssertionStatus(String, boolean)
- * @since 1.4
- */
- public synchronized void clearAssertionStatus()
- {
- defaultAssertionStatus = false;
- packageAssertionStatus = new HashMap();
- classAssertionStatus = new HashMap();
- }
- /**
- * Return true if this loader is either the specified class loader
- * or an ancestor thereof.
- * @param loader the class loader to check
- */
- final boolean isAncestorOf(ClassLoader loader)
- {
- while (loader != null)
- {
- if (this == loader)
- return true;
- loader = loader.parent;
- }
- return false;
- }
- /**
- * Before doing anything "dangerous" please call this method to make sure
- * this class loader instance was properly constructed (and not obtained
- * by exploiting the finalizer attack)
- * @see #initialized
- */
- private void checkInitialized()
- {
- if (! initialized)
- throw new SecurityException("attempt to use uninitialized class loader");
- }
- }
|