Save This Page
Home » openjdk-7 » java » lang » [javadoc | source]
    1   /*
    2    * Copyright 1994-2005 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   package java.lang;
   26   
   27   import java.io.InputStream;
   28   import java.io.IOException;
   29   import java.io.File;
   30   import java.lang.reflect.Constructor;
   31   import java.lang.reflect.InvocationTargetException;
   32   import java.net.MalformedURLException;
   33   import java.net.URL;
   34   import java.security.AccessController;
   35   import java.security.AccessControlContext;
   36   import java.security.CodeSource;
   37   import java.security.Policy;
   38   import java.security.PrivilegedAction;
   39   import java.security.PrivilegedActionException;
   40   import java.security.PrivilegedExceptionAction;
   41   import java.security.ProtectionDomain;
   42   import java.security.cert.Certificate;
   43   import java.util.Enumeration;
   44   import java.util.Hashtable;
   45   import java.util.HashMap;
   46   import java.util.HashSet;
   47   import java.util.Set;
   48   import java.util.Stack;
   49   import java.util.Map;
   50   import java.util.Vector;
   51   import sun.misc.ClassFileTransformer;
   52   import sun.misc.CompoundEnumeration;
   53   import sun.misc.Resource;
   54   import sun.misc.URLClassPath;
   55   import sun.misc.VM;
   56   import sun.reflect.Reflection;
   57   import sun.security.util.SecurityConstants;
   58   
   59   /**
   60    * A class loader is an object that is responsible for loading classes. The
   61    * class <tt>ClassLoader</tt> is an abstract class.  Given the <a
   62    * href="#name">binary name</a> of a class, a class loader should attempt to
   63    * locate or generate data that constitutes a definition for the class.  A
   64    * typical strategy is to transform the name into a file name and then read a
   65    * "class file" of that name from a file system.
   66    *
   67    * <p> Every {@link Class <tt>Class</tt>} object contains a {@link
   68    * Class#getClassLoader() reference} to the <tt>ClassLoader</tt> that defined
   69    * it.
   70    *
   71    * <p> <tt>Class</tt> objects for array classes are not created by class
   72    * loaders, but are created automatically as required by the Java runtime.
   73    * The class loader for an array class, as returned by {@link
   74    * Class#getClassLoader()} is the same as the class loader for its element
   75    * type; if the element type is a primitive type, then the array class has no
   76    * class loader.
   77    *
   78    * <p> Applications implement subclasses of <tt>ClassLoader</tt> in order to
   79    * extend the manner in which the Java virtual machine dynamically loads
   80    * classes.
   81    *
   82    * <p> Class loaders may typically be used by security managers to indicate
   83    * security domains.
   84    *
   85    * <p> The <tt>ClassLoader</tt> class uses a delegation model to search for
   86    * classes and resources.  Each instance of <tt>ClassLoader</tt> has an
   87    * associated parent class loader.  When requested to find a class or
   88    * resource, a <tt>ClassLoader</tt> instance will delegate the search for the
   89    * class or resource to its parent class loader before attempting to find the
   90    * class or resource itself.  The virtual machine's built-in class loader,
   91    * called the "bootstrap class loader", does not itself have a parent but may
   92    * serve as the parent of a <tt>ClassLoader</tt> instance.
   93    *
   94    * <p> Normally, the Java virtual machine loads classes from the local file
   95    * system in a platform-dependent manner.  For example, on UNIX systems, the
   96    * virtual machine loads classes from the directory defined by the
   97    * <tt>CLASSPATH</tt> environment variable.
   98    *
   99    * <p> However, some classes may not originate from a file; they may originate
  100    * from other sources, such as the network, or they could be constructed by an
  101    * application.  The method {@link #defineClass(String, byte[], int, int)
  102    * <tt>defineClass</tt>} converts an array of bytes into an instance of class
  103    * <tt>Class</tt>. Instances of this newly defined class can be created using
  104    * {@link Class#newInstance <tt>Class.newInstance</tt>}.
  105    *
  106    * <p> The methods and constructors of objects created by a class loader may
  107    * reference other classes.  To determine the class(es) referred to, the Java
  108    * virtual machine invokes the {@link #loadClass <tt>loadClass</tt>} method of
  109    * the class loader that originally created the class.
  110    *
  111    * <p> For example, an application could create a network class loader to
  112    * download class files from a server.  Sample code might look like:
  113    *
  114    * <blockquote><pre>
  115    *   ClassLoader loader&nbsp;= new NetworkClassLoader(host,&nbsp;port);
  116    *   Object main&nbsp;= loader.loadClass("Main", true).newInstance();
  117    *       &nbsp;.&nbsp;.&nbsp;.
  118    * </pre></blockquote>
  119    *
  120    * <p> The network class loader subclass must define the methods {@link
  121    * #findClass <tt>findClass</tt>} and <tt>loadClassData</tt> to load a class
  122    * from the network.  Once it has downloaded the bytes that make up the class,
  123    * it should use the method {@link #defineClass <tt>defineClass</tt>} to
  124    * create a class instance.  A sample implementation is:
  125    *
  126    * <blockquote><pre>
  127    *     class NetworkClassLoader extends ClassLoader {
  128    *         String host;
  129    *         int port;
  130    *
  131    *         public Class findClass(String name) {
  132    *             byte[] b = loadClassData(name);
  133    *             return defineClass(name, b, 0, b.length);
  134    *         }
  135    *
  136    *         private byte[] loadClassData(String name) {
  137    *             // load the class data from the connection
  138    *             &nbsp;.&nbsp;.&nbsp;.
  139    *         }
  140    *     }
  141    * </pre></blockquote>
  142    *
  143    * <h4> <a name="name">Binary names</a> </h4>
  144    *
  145    * <p> Any class name provided as a {@link String} parameter to methods in
  146    * <tt>ClassLoader</tt> must be a binary name as defined by the <a
  147    * href="http://java.sun.com/docs/books/jls/">Java Language Specification</a>.
  148    *
  149    * <p> Examples of valid class names include:
  150    * <blockquote><pre>
  151    *   "java.lang.String"
  152    *   "javax.swing.JSpinner$DefaultEditor"
  153    *   "java.security.KeyStore$Builder$FileBuilder$1"
  154    *   "java.net.URLClassLoader$3$1"
  155    * </pre></blockquote>
  156    *
  157    * @see      #resolveClass(Class)
  158    * @since 1.0
  159    */
  160   public abstract class ClassLoader {
  161   
  162       private static native void registerNatives();
  163       static {
  164           registerNatives();
  165       }
  166   
  167       // If initialization succeed this is set to true and security checks will
  168       // succeed.  Otherwise the object is not initialized and the object is
  169       // useless.
  170       private boolean initialized = false;
  171   
  172       // The parent class loader for delegation
  173       private ClassLoader parent;
  174   
  175       // Hashtable that maps packages to certs
  176       private Hashtable<String, Certificate[]> package2certs
  177           = new Hashtable<String, Certificate[]>(11);
  178   
  179       // Shared among all packages with unsigned classes
  180       Certificate[] nocerts;
  181   
  182       // The classes loaded by this class loader.  The only purpose of this table
  183       // is to keep the classes from being GC'ed until the loader is GC'ed.
  184       private Vector<Class<?>> classes = new Vector<Class<?>>();
  185   
  186       // The initiating protection domains for all classes loaded by this loader
  187       private Set<ProtectionDomain> domains = new HashSet<ProtectionDomain>();
  188   
  189       // Invoked by the VM to record every loaded class with this loader.
  190       void addClass(Class c) {
  191           classes.addElement(c);
  192       }
  193   
  194       // The packages defined in this class loader.  Each package name is mapped
  195       // to its corresponding Package object.
  196       private HashMap<String, Package> packages = new HashMap<String, Package>();
  197   
  198       /**
  199        * Creates a new class loader using the specified parent class loader for
  200        * delegation.
  201        *
  202        * <p> If there is a security manager, its {@link
  203        * SecurityManager#checkCreateClassLoader()
  204        * <tt>checkCreateClassLoader</tt>} method is invoked.  This may result in
  205        * a security exception.  </p>
  206        *
  207        * @param  parent
  208        *         The parent class loader
  209        *
  210        * @throws  SecurityException
  211        *          If a security manager exists and its
  212        *          <tt>checkCreateClassLoader</tt> method doesn't allow creation
  213        *          of a new class loader.
  214        *
  215        * @since  1.2
  216        */
  217       protected ClassLoader(ClassLoader parent) {
  218           SecurityManager security = System.getSecurityManager();
  219           if (security != null) {
  220               security.checkCreateClassLoader();
  221           }
  222           this.parent = parent;
  223           initialized = true;
  224       }
  225   
  226       /**
  227        * Creates a new class loader using the <tt>ClassLoader</tt> returned by
  228        * the method {@link #getSystemClassLoader()
  229        * <tt>getSystemClassLoader()</tt>} as the parent class loader.
  230        *
  231        * <p> If there is a security manager, its {@link
  232        * SecurityManager#checkCreateClassLoader()
  233        * <tt>checkCreateClassLoader</tt>} method is invoked.  This may result in
  234        * a security exception.  </p>
  235        *
  236        * @throws  SecurityException
  237        *          If a security manager exists and its
  238        *          <tt>checkCreateClassLoader</tt> method doesn't allow creation
  239        *          of a new class loader.
  240        */
  241       protected ClassLoader() {
  242           SecurityManager security = System.getSecurityManager();
  243           if (security != null) {
  244               security.checkCreateClassLoader();
  245           }
  246           this.parent = getSystemClassLoader();
  247           initialized = true;
  248       }
  249   
  250   
  251       // -- Class --
  252   
  253       /**
  254        * Loads the class with the specified <a href="#name">binary name</a>.
  255        * This method searches for classes in the same manner as the {@link
  256        * #loadClass(String, boolean)} method.  It is invoked by the Java virtual
  257        * machine to resolve class references.  Invoking this method is equivalent
  258        * to invoking {@link #loadClass(String, boolean) <tt>loadClass(name,
  259        * false)</tt>}.  </p>
  260        *
  261        * @param  name
  262        *         The <a href="#name">binary name</a> of the class
  263        *
  264        * @return  The resulting <tt>Class</tt> object
  265        *
  266        * @throws  ClassNotFoundException
  267        *          If the class was not found
  268        */
  269       public Class<?> loadClass(String name) throws ClassNotFoundException {
  270           return loadClass(name, false);
  271       }
  272   
  273       /**
  274        * Loads the class with the specified <a href="#name">binary name</a>.  The
  275        * default implementation of this method searches for classes in the
  276        * following order:
  277        *
  278        * <p><ol>
  279        *
  280        *   <li><p> Invoke {@link #findLoadedClass(String)} to check if the class
  281        *   has already been loaded.  </p></li>
  282        *
  283        *   <li><p> Invoke the {@link #loadClass(String) <tt>loadClass</tt>} method
  284        *   on the parent class loader.  If the parent is <tt>null</tt> the class
  285        *   loader built-in to the virtual machine is used, instead.  </p></li>
  286        *
  287        *   <li><p> Invoke the {@link #findClass(String)} method to find the
  288        *   class.  </p></li>
  289        *
  290        * </ol>
  291        *
  292        * <p> If the class was found using the above steps, and the
  293        * <tt>resolve</tt> flag is true, this method will then invoke the {@link
  294        * #resolveClass(Class)} method on the resulting <tt>Class</tt> object.
  295        *
  296        * <p> Subclasses of <tt>ClassLoader</tt> are encouraged to override {@link
  297        * #findClass(String)}, rather than this method.  </p>
  298        *
  299        * @param  name
  300        *         The <a href="#name">binary name</a> of the class
  301        *
  302        * @param  resolve
  303        *         If <tt>true</tt> then resolve the class
  304        *
  305        * @return  The resulting <tt>Class</tt> object
  306        *
  307        * @throws  ClassNotFoundException
  308        *          If the class could not be found
  309        */
  310       protected synchronized Class<?> loadClass(String name, boolean resolve)
  311           throws ClassNotFoundException
  312       {
  313           // First, check if the class has already been loaded
  314           Class c = findLoadedClass(name);
  315           if (c == null) {
  316               try {
  317                   if (parent != null) {
  318                       c = parent.loadClass(name, false);
  319                   } else {
  320                       c = findBootstrapClass0(name);
  321                   }
  322               } catch (ClassNotFoundException e) {
  323                   // If still not found, then invoke findClass in order
  324                   // to find the class.
  325                   c = findClass(name);
  326               }
  327           }
  328           if (resolve) {
  329               resolveClass(c);
  330           }
  331           return c;
  332       }
  333   
  334       // This method is invoked by the virtual machine to load a class.
  335       private synchronized Class loadClassInternal(String name)
  336           throws ClassNotFoundException
  337       {
  338           return loadClass(name);
  339       }
  340   
  341       private void checkPackageAccess(Class cls, ProtectionDomain pd) {
  342           final SecurityManager sm = System.getSecurityManager();
  343           if (sm != null) {
  344               final String name = cls.getName();
  345               final int i = name.lastIndexOf('.');
  346               if (i != -1) {
  347                   AccessController.doPrivileged(new PrivilegedAction<Void>() {
  348                       public Void run() {
  349                           sm.checkPackageAccess(name.substring(0, i));
  350                           return null;
  351                       }
  352                   }, new AccessControlContext(new ProtectionDomain[] {pd}));
  353               }
  354           }
  355           domains.add(pd);
  356       }
  357   
  358       /**
  359        * Finds the class with the specified <a href="#name">binary name</a>.
  360        * This method should be overridden by class loader implementations that
  361        * follow the delegation model for loading classes, and will be invoked by
  362        * the {@link #loadClass <tt>loadClass</tt>} method after checking the
  363        * parent class loader for the requested class.  The default implementation
  364        * throws a <tt>ClassNotFoundException</tt>.  </p>
  365        *
  366        * @param  name
  367        *         The <a href="#name">binary name</a> of the class
  368        *
  369        * @return  The resulting <tt>Class</tt> object
  370        *
  371        * @throws  ClassNotFoundException
  372        *          If the class could not be found
  373        *
  374        * @since  1.2
  375        */
  376       protected Class<?> findClass(String name) throws ClassNotFoundException {
  377           throw new ClassNotFoundException(name);
  378       }
  379   
  380       /**
  381        * Converts an array of bytes into an instance of class <tt>Class</tt>.
  382        * Before the <tt>Class</tt> can be used it must be resolved.  This method
  383        * is deprecated in favor of the version that takes a <a
  384        * href="#name">binary name</a> as its first argument, and is more secure.
  385        *
  386        * @param  b
  387        *         The bytes that make up the class data.  The bytes in positions
  388        *         <tt>off</tt> through <tt>off+len-1</tt> should have the format
  389        *         of a valid class file as defined by the <a
  390        *         href="http://java.sun.com/docs/books/vmspec/">Java Virtual
  391        *         Machine Specification</a>.
  392        *
  393        * @param  off
  394        *         The start offset in <tt>b</tt> of the class data
  395        *
  396        * @param  len
  397        *         The length of the class data
  398        *
  399        * @return  The <tt>Class</tt> object that was created from the specified
  400        *          class data
  401        *
  402        * @throws  ClassFormatError
  403        *          If the data did not contain a valid class
  404        *
  405        * @throws  IndexOutOfBoundsException
  406        *          If either <tt>off</tt> or <tt>len</tt> is negative, or if
  407        *          <tt>off+len</tt> is greater than <tt>b.length</tt>.
  408        *
  409        * @see  #loadClass(String, boolean)
  410        * @see  #resolveClass(Class)
  411        *
  412        * @deprecated  Replaced by {@link #defineClass(String, byte[], int, int)
  413        * defineClass(String, byte[], int, int)}
  414        */
  415       @Deprecated
  416       protected final Class<?> defineClass(byte[] b, int off, int len)
  417           throws ClassFormatError
  418       {
  419           return defineClass(null, b, off, len, null);
  420       }
  421   
  422       /**
  423        * Converts an array of bytes into an instance of class <tt>Class</tt>.
  424        * Before the <tt>Class</tt> can be used it must be resolved.
  425        *
  426        * <p> This method assigns a default {@link java.security.ProtectionDomain
  427        * <tt>ProtectionDomain</tt>} to the newly defined class.  The
  428        * <tt>ProtectionDomain</tt> is effectively granted the same set of
  429        * permissions returned when {@link
  430        * java.security.Policy#getPermissions(java.security.CodeSource)
  431        * <tt>Policy.getPolicy().getPermissions(new CodeSource(null, null))</tt>}
  432        * is invoked.  The default domain is created on the first invocation of
  433        * {@link #defineClass(String, byte[], int, int) <tt>defineClass</tt>},
  434        * and re-used on subsequent invocations.
  435        *
  436        * <p> To assign a specific <tt>ProtectionDomain</tt> to the class, use
  437        * the {@link #defineClass(String, byte[], int, int,
  438        * java.security.ProtectionDomain) <tt>defineClass</tt>} method that takes a
  439        * <tt>ProtectionDomain</tt> as one of its arguments.  </p>
  440        *
  441        * @param  name
  442        *         The expected <a href="#name">binary name</a> of the class, or
  443        *         <tt>null</tt> if not known
  444        *
  445        * @param  b
  446        *         The bytes that make up the class data.  The bytes in positions
  447        *         <tt>off</tt> through <tt>off+len-1</tt> should have the format
  448        *         of a valid class file as defined by the <a
  449        *         href="http://java.sun.com/docs/books/vmspec/">Java Virtual
  450        *         Machine Specification</a>.
  451        *
  452        * @param  off
  453        *         The start offset in <tt>b</tt> of the class data
  454        *
  455        * @param  len
  456        *         The length of the class data
  457        *
  458        * @return  The <tt>Class</tt> object that was created from the specified
  459        *          class data.
  460        *
  461        * @throws  ClassFormatError
  462        *          If the data did not contain a valid class
  463        *
  464        * @throws  IndexOutOfBoundsException
  465        *          If either <tt>off</tt> or <tt>len</tt> is negative, or if
  466        *          <tt>off+len</tt> is greater than <tt>b.length</tt>.
  467        *
  468        * @throws  SecurityException
  469        *          If an attempt is made to add this class to a package that
  470        *          contains classes that were signed by a different set of
  471        *          certificates than this class (which is unsigned), or if
  472        *          <tt>name</tt> begins with "<tt>java.</tt>".
  473        *
  474        * @see  #loadClass(String, boolean)
  475        * @see  #resolveClass(Class)
  476        * @see  java.security.CodeSource
  477        * @see  java.security.SecureClassLoader
  478        *
  479        * @since  1.1
  480        */
  481       protected final Class<?> defineClass(String name, byte[] b, int off, int len)
  482           throws ClassFormatError
  483       {
  484           return defineClass(name, b, off, len, null);
  485       }
  486   
  487       /* Determine protection domain, and check that:
  488           - not define java.* class,
  489           - signer of this class matches signers for the rest of the classes in package.
  490       */
  491       private ProtectionDomain preDefineClass(String name,
  492                                               ProtectionDomain protectionDomain)
  493       {
  494           if (!checkName(name))
  495               throw new NoClassDefFoundError("IllegalName: " + name);
  496   
  497           if ((name != null) && name.startsWith("java.")) {
  498               throw new SecurityException("Prohibited package name: " +
  499                                           name.substring(0, name.lastIndexOf('.')));
  500           }
  501           if (protectionDomain == null) {
  502               protectionDomain = getDefaultDomain();
  503           }
  504   
  505           if (name != null)
  506               checkCerts(name, protectionDomain.getCodeSource());
  507   
  508           return protectionDomain;
  509       }
  510   
  511       private String defineClassSourceLocation(ProtectionDomain protectionDomain)
  512       {
  513           CodeSource cs = protectionDomain.getCodeSource();
  514           String source = null;
  515           if (cs != null && cs.getLocation() != null) {
  516               source = cs.getLocation().toString();
  517           }
  518           return source;
  519       }
  520   
  521       private Class defineTransformedClass(String name, byte[] b, int off, int len,
  522                                            ProtectionDomain protectionDomain,
  523                                            ClassFormatError cfe, String source)
  524         throws ClassFormatError
  525       {
  526           // Class format error - try to transform the bytecode and
  527           // define the class again
  528           //
  529           ClassFileTransformer[] transformers = ClassFileTransformer.getTransformers();
  530           Class c = null;
  531   
  532           if (transformers != null) {
  533               for (ClassFileTransformer transformer : transformers) {
  534                   try {
  535                       // Transform byte code using transformer
  536                       byte[] tb = transformer.transform(b, off, len);
  537                       c = defineClass1(name, tb, 0, tb.length,
  538                                        protectionDomain, source);
  539                       break;
  540                   } catch (ClassFormatError cfe2)     {
  541                       // If ClassFormatError occurs, try next transformer
  542                   }
  543               }
  544           }
  545   
  546           // Rethrow original ClassFormatError if unable to transform
  547           // bytecode to well-formed
  548           //
  549           if (c == null)
  550               throw cfe;
  551   
  552           return c;
  553       }
  554   
  555       private void postDefineClass(Class c, ProtectionDomain protectionDomain)
  556       {
  557           if (protectionDomain.getCodeSource() != null) {
  558               Certificate certs[] =
  559                   protectionDomain.getCodeSource().getCertificates();
  560               if (certs != null)
  561                   setSigners(c, certs);
  562           }
  563       }
  564   
  565       /**
  566        * Converts an array of bytes into an instance of class <tt>Class</tt>,
  567        * with an optional <tt>ProtectionDomain</tt>.  If the domain is
  568        * <tt>null</tt>, then a default domain will be assigned to the class as
  569        * specified in the documentation for {@link #defineClass(String, byte[],
  570        * int, int)}.  Before the class can be used it must be resolved.
  571        *
  572        * <p> The first class defined in a package determines the exact set of
  573        * certificates that all subsequent classes defined in that package must
  574        * contain.  The set of certificates for a class is obtained from the
  575        * {@link java.security.CodeSource <tt>CodeSource</tt>} within the
  576        * <tt>ProtectionDomain</tt> of the class.  Any classes added to that
  577        * package must contain the same set of certificates or a
  578        * <tt>SecurityException</tt> will be thrown.  Note that if
  579        * <tt>name</tt> is <tt>null</tt>, this check is not performed.
  580        * You should always pass in the <a href="#name">binary name</a> of the
  581        * class you are defining as well as the bytes.  This ensures that the
  582        * class you are defining is indeed the class you think it is.
  583        *
  584        * <p> The specified <tt>name</tt> cannot begin with "<tt>java.</tt>", since
  585        * all classes in the "<tt>java.*</tt> packages can only be defined by the
  586        * bootstrap class loader.  If <tt>name</tt> is not <tt>null</tt>, it
  587        * must be equal to the <a href="#name">binary name</a> of the class
  588        * specified by the byte array "<tt>b</tt>", otherwise a {@link
  589        * <tt>NoClassDefFoundError</tt>} will be thrown.  </p>
  590        *
  591        * @param  name
  592        *         The expected <a href="#name">binary name</a> of the class, or
  593        *         <tt>null</tt> if not known
  594        *
  595        * @param  b
  596        *         The bytes that make up the class data. The bytes in positions
  597        *         <tt>off</tt> through <tt>off+len-1</tt> should have the format
  598        *         of a valid class file as defined by the <a
  599        *         href="http://java.sun.com/docs/books/vmspec/">Java Virtual
  600        *         Machine Specification</a>.
  601        *
  602        * @param  off
  603        *         The start offset in <tt>b</tt> of the class data
  604        *
  605        * @param  len
  606        *         The length of the class data
  607        *
  608        * @param  protectionDomain
  609        *         The ProtectionDomain of the class
  610        *
  611        * @return  The <tt>Class</tt> object created from the data,
  612        *          and optional <tt>ProtectionDomain</tt>.
  613        *
  614        * @throws  ClassFormatError
  615        *          If the data did not contain a valid class
  616        *
  617        * @throws  NoClassDefFoundError
  618        *          If <tt>name</tt> is not equal to the <a href="#name">binary
  619        *          name</a> of the class specified by <tt>b</tt>
  620        *
  621        * @throws  IndexOutOfBoundsException
  622        *          If either <tt>off</tt> or <tt>len</tt> is negative, or if
  623        *          <tt>off+len</tt> is greater than <tt>b.length</tt>.
  624        *
  625        * @throws  SecurityException
  626        *          If an attempt is made to add this class to a package that
  627        *          contains classes that were signed by a different set of
  628        *          certificates than this class, or if <tt>name</tt> begins with
  629        *          "<tt>java.</tt>".
  630        */
  631       protected final Class<?> defineClass(String name, byte[] b, int off, int len,
  632                                            ProtectionDomain protectionDomain)
  633           throws ClassFormatError
  634       {
  635           check();
  636           protectionDomain = preDefineClass(name, protectionDomain);
  637   
  638           Class c = null;
  639           String source = defineClassSourceLocation(protectionDomain);
  640   
  641           try {
  642               c = defineClass1(name, b, off, len, protectionDomain, source);
  643           } catch (ClassFormatError cfe) {
  644               c = defineTransformedClass(name, b, off, len, protectionDomain, cfe, source);
  645           }
  646   
  647           postDefineClass(c, protectionDomain);
  648           return c;
  649       }
  650   
  651       /**
  652        * Converts a {@link java.nio.ByteBuffer <tt>ByteBuffer</tt>}
  653        * into an instance of class <tt>Class</tt>,
  654        * with an optional <tt>ProtectionDomain</tt>.  If the domain is
  655        * <tt>null</tt>, then a default domain will be assigned to the class as
  656        * specified in the documentation for {@link #defineClass(String, byte[],
  657        * int, int)}.  Before the class can be used it must be resolved.
  658        *
  659        * <p>The rules about the first class defined in a package determining the set of
  660        * certificates for the package, and the restrictions on class names are identical
  661        * to those specified in the documentation for {@link #defineClass(String, byte[],
  662        * int, int, ProtectionDomain)}.
  663        *
  664        * <p> An invocation of this method of the form
  665        * <i>cl</i><tt>.defineClass(</tt><i>name</i><tt>,</tt>
  666        * <i>bBuffer</i><tt>,</tt> <i>pd</i><tt>)</tt> yields exactly the same
  667        * result as the statements
  668        *
  669        * <blockquote><tt>
  670        * ...<br>
  671        * byte[] temp = new byte[</tt><i>bBuffer</i><tt>.{@link java.nio.ByteBuffer#remaining
  672        * remaining}()];<br>
  673        *     </tt><i>bBuffer</i><tt>.{@link java.nio.ByteBuffer#get(byte[])
  674        * get}(temp);<br>
  675        *     return {@link #defineClass(String, byte[], int, int, ProtectionDomain)
  676        * </tt><i>cl</i><tt>.defineClass}(</tt><i>name</i><tt>, temp, 0, temp.length, </tt><i>pd</i><tt>);<br>
  677        * </tt></blockquote>
  678        *
  679        * @param  name
  680        *         The expected <a href="#name">binary name</a. of the class, or
  681        *         <tt>null</tt> if not known
  682        *
  683        * @param  b
  684        *         The bytes that make up the class data. The bytes from positions
  685        *         <tt>b.position()</tt> through <tt>b.position() + b.limit() -1 </tt>
  686        *         should have the format of a valid class file as defined by the <a
  687        *         href="http://java.sun.com/docs/books/vmspec/">Java Virtual
  688        *         Machine Specification</a>.
  689        *
  690        * @param  protectionDomain
  691        *         The ProtectionDomain of the class, or <tt>null</tt>.
  692        *
  693        * @return  The <tt>Class</tt> object created from the data,
  694        *          and optional <tt>ProtectionDomain</tt>.
  695        *
  696        * @throws  ClassFormatError
  697        *          If the data did not contain a valid class.
  698        *
  699        * @throws  NoClassDefFoundError
  700        *          If <tt>name</tt> is not equal to the <a href="#name">binary
  701        *          name</a> of the class specified by <tt>b</tt>
  702        *
  703        * @throws  SecurityException
  704        *          If an attempt is made to add this class to a package that
  705        *          contains classes that were signed by a different set of
  706        *          certificates than this class, or if <tt>name</tt> begins with
  707        *          "<tt>java.</tt>".
  708        *
  709        * @see      #defineClass(String, byte[], int, int, ProtectionDomain)
  710        *
  711        * @since  1.5
  712        */
  713       protected final Class<?> defineClass(String name, java.nio.ByteBuffer b,
  714                                            ProtectionDomain protectionDomain)
  715           throws ClassFormatError
  716       {
  717           check();
  718   
  719           int len = b.remaining();
  720   
  721           // Use byte[] if not a direct ByteBufer:
  722           if (!b.isDirect()) {
  723               if (b.hasArray()) {
  724                   return defineClass(name, b.array(),
  725                                      b.position() + b.arrayOffset(), len,
  726                                      protectionDomain);
  727               } else {
  728                   // no array, or read-only array
  729                   byte[] tb = new byte[len];
  730                   b.get(tb);  // get bytes out of byte buffer.
  731                   return defineClass(name, tb, 0, len, protectionDomain);
  732               }
  733           }
  734   
  735           protectionDomain = preDefineClass(name, protectionDomain);
  736   
  737           Class c = null;
  738           String source = defineClassSourceLocation(protectionDomain);
  739   
  740           try {
  741               c = defineClass2(name, b, b.position(), len, protectionDomain, source);
  742           } catch (ClassFormatError cfe) {
  743               byte[] tb = new byte[len];
  744               b.get(tb);  // get bytes out of byte buffer.
  745               c = defineTransformedClass(name, tb, 0, len, protectionDomain, cfe, source);
  746           }
  747   
  748           postDefineClass(c, protectionDomain);
  749           return c;
  750       }
  751   
  752       private native Class defineClass0(String name, byte[] b, int off, int len,
  753                                         ProtectionDomain pd);
  754   
  755       private native Class defineClass1(String name, byte[] b, int off, int len,
  756                                         ProtectionDomain pd, String source);
  757   
  758       private native Class defineClass2(String name, java.nio.ByteBuffer b,
  759                                         int off, int len, ProtectionDomain pd,
  760                                         String source);
  761   
  762       // true if the name is null or has the potential to be a valid binary name
  763       private boolean checkName(String name) {
  764           if ((name == null) || (name.length() == 0))
  765               return true;
  766           if ((name.indexOf('/') != -1)
  767               || (!VM.allowArraySyntax() && (name.charAt(0) == '[')))
  768               return false;
  769           return true;
  770       }
  771   
  772       private synchronized void checkCerts(String name, CodeSource cs) {
  773           int i = name.lastIndexOf('.');
  774           String pname = (i == -1) ? "" : name.substring(0, i);
  775           Certificate[] pcerts = package2certs.get(pname);
  776           if (pcerts == null) {
  777               // first class in this package gets to define which
  778               // certificates must be the same for all other classes
  779               // in this package
  780               if (cs != null) {
  781                   pcerts = cs.getCertificates();
  782               }
  783               if (pcerts == null) {
  784                   if (nocerts == null)
  785                       nocerts = new Certificate[0];
  786                   pcerts = nocerts;
  787               }
  788               package2certs.put(pname, pcerts);
  789           } else {
  790               Certificate[] certs = null;
  791               if (cs != null) {
  792                   certs = cs.getCertificates();
  793               }
  794   
  795               if (!compareCerts(pcerts, certs)) {
  796                   throw new SecurityException("class \""+ name +
  797                                               "\"'s signer information does not match signer information of other classes in the same package");
  798               }
  799           }
  800       }
  801   
  802       /**
  803        * check to make sure the certs for the new class (certs) are the same as
  804        * the certs for the first class inserted in the package (pcerts)
  805        */
  806       private boolean compareCerts(Certificate[] pcerts,
  807                                    Certificate[] certs)
  808       {
  809           // certs can be null, indicating no certs.
  810           if ((certs == null) || (certs.length == 0)) {
  811               return pcerts.length == 0;
  812           }
  813   
  814           // the length must be the same at this point
  815           if (certs.length != pcerts.length)
  816               return false;
  817   
  818           // go through and make sure all the certs in one array
  819           // are in the other and vice-versa.
  820           boolean match;
  821           for (int i = 0; i < certs.length; i++) {
  822               match = false;
  823               for (int j = 0; j < pcerts.length; j++) {
  824                   if (certs[i].equals(pcerts[j])) {
  825                       match = true;
  826                       break;
  827                   }
  828               }
  829               if (!match) return false;
  830           }
  831   
  832           // now do the same for pcerts
  833           for (int i = 0; i < pcerts.length; i++) {
  834               match = false;
  835               for (int j = 0; j < certs.length; j++) {
  836                   if (pcerts[i].equals(certs[j])) {
  837                       match = true;
  838                       break;
  839                   }
  840               }
  841               if (!match) return false;
  842           }
  843   
  844           return true;
  845       }
  846   
  847       /**
  848        * Links the specified class.  This (misleadingly named) method may be
  849        * used by a class loader to link a class.  If the class <tt>c</tt> has
  850        * already been linked, then this method simply returns. Otherwise, the
  851        * class is linked as described in the "Execution" chapter of the <a
  852        * href="http://java.sun.com/docs/books/jls/">Java Language
  853        * Specification</a>.
  854        * </p>
  855        *
  856        * @param  c
  857        *         The class to link
  858        *
  859        * @throws  NullPointerException
  860        *          If <tt>c</tt> is <tt>null</tt>.
  861        *
  862        * @see  #defineClass(String, byte[], int, int)
  863        */
  864       protected final void resolveClass(Class<?> c) {
  865           check();
  866           resolveClass0(c);
  867       }
  868   
  869       private native void resolveClass0(Class c);
  870   
  871       /**
  872        * Finds a class with the specified <a href="#name">binary name</a>,
  873        * loading it if necessary.
  874        *
  875        * <p> This method loads the class through the system class loader (see
  876        * {@link #getSystemClassLoader()}).  The <tt>Class</tt> object returned
  877        * might have more than one <tt>ClassLoader</tt> associated with it.
  878        * Subclasses of <tt>ClassLoader</tt> need not usually invoke this method,
  879        * because most class loaders need to override just {@link
  880        * #findClass(String)}.  </p>
  881        *
  882        * @param  name
  883        *         The <a href="#name">binary name</a> of the class
  884        *
  885        * @return  The <tt>Class</tt> object for the specified <tt>name</tt>
  886        *
  887        * @throws  ClassNotFoundException
  888        *          If the class could not be found
  889        *
  890        * @see  #ClassLoader(ClassLoader)
  891        * @see  #getParent()
  892        */
  893       protected final Class<?> findSystemClass(String name)
  894           throws ClassNotFoundException
  895       {
  896           check();
  897           ClassLoader system = getSystemClassLoader();
  898           if (system == null) {
  899               if (!checkName(name))
  900                   throw new ClassNotFoundException(name);
  901               return findBootstrapClass(name);
  902           }
  903           return system.loadClass(name);
  904       }
  905   
  906       private Class findBootstrapClass0(String name)
  907           throws ClassNotFoundException
  908       {
  909           check();
  910           if (!checkName(name))
  911               throw new ClassNotFoundException(name);
  912           return findBootstrapClass(name);
  913       }
  914   
  915       private native Class findBootstrapClass(String name)
  916           throws ClassNotFoundException;
  917   
  918       // Check to make sure the class loader has been initialized.
  919       private void check() {
  920           if (!initialized) {
  921               throw new SecurityException("ClassLoader object not initialized");
  922           }
  923       }
  924   
  925       /**
  926        * Returns the class with the given <a href="#name">binary name</a> if this
  927        * loader has been recorded by the Java virtual machine as an initiating
  928        * loader of a class with that <a href="#name">binary name</a>.  Otherwise
  929        * <tt>null</tt> is returned.  </p>
  930        *
  931        * @param  name
  932        *         The <a href="#name">binary name</a> of the class
  933        *
  934        * @return  The <tt>Class</tt> object, or <tt>null</tt> if the class has
  935        *          not been loaded
  936        *
  937        * @since  1.1
  938        */
  939       protected final Class<?> findLoadedClass(String name) {
  940           check();
  941           if (!checkName(name))
  942               return null;
  943           return findLoadedClass0(name);
  944       }
  945   
  946       private native final Class findLoadedClass0(String name);
  947   
  948       /**
  949        * Sets the signers of a class.  This should be invoked after defining a
  950        * class.  </p>
  951        *
  952        * @param  c
  953        *         The <tt>Class</tt> object
  954        *
  955        * @param  signers
  956        *         The signers for the class
  957        *
  958        * @since  1.1
  959        */
  960       protected final void setSigners(Class<?> c, Object[] signers) {
  961           check();
  962           c.setSigners(signers);
  963       }
  964   
  965   
  966       // -- Resource --
  967   
  968       /**
  969        * Finds the resource with the given name.  A resource is some data
  970        * (images, audio, text, etc) that can be accessed by class code in a way
  971        * that is independent of the location of the code.
  972        *
  973        * <p> The name of a resource is a '<tt>/</tt>'-separated path name that
  974        * identifies the resource.
  975        *
  976        * <p> This method will first search the parent class loader for the
  977        * resource; if the parent is <tt>null</tt> the path of the class loader
  978        * built-in to the virtual machine is searched.  That failing, this method
  979        * will invoke {@link #findResource(String)} to find the resource.  </p>
  980        *
  981        * @param  name
  982        *         The resource name
  983        *
  984        * @return  A <tt>URL</tt> object for reading the resource, or
  985        *          <tt>null</tt> if the resource could not be found or the invoker
  986        *          doesn't have adequate  privileges to get the resource.
  987        *
  988        * @since  1.1
  989        */
  990       public URL getResource(String name) {
  991           URL url;
  992           if (parent != null) {
  993               url = parent.getResource(name);
  994           } else {
  995               url = getBootstrapResource(name);
  996           }
  997           if (url == null) {
  998               url = findResource(name);
  999           }
 1000           return url;
 1001       }
 1002   
 1003       /**
 1004        * Finds all the resources with the given name. A resource is some data
 1005        * (images, audio, text, etc) that can be accessed by class code in a way
 1006        * that is independent of the location of the code.
 1007        *
 1008        * <p>The name of a resource is a <tt>/</tt>-separated path name that
 1009        * identifies the resource.
 1010        *
 1011        * <p> The search order is described in the documentation for {@link
 1012        * #getResource(String)}.  </p>
 1013        *
 1014        * @param  name
 1015        *         The resource name
 1016        *
 1017        * @return  An enumeration of {@link java.net.URL <tt>URL</tt>} objects for
 1018        *          the resource.  If no resources could  be found, the enumeration
 1019        *          will be empty.  Resources that the class loader doesn't have
 1020        *          access to will not be in the enumeration.
 1021        *
 1022        * @throws  IOException
 1023        *          If I/O errors occur
 1024        *
 1025        * @see  #findResources(String)
 1026        *
 1027        * @since  1.2
 1028        */
 1029       public Enumeration<URL> getResources(String name) throws IOException {
 1030           Enumeration[] tmp = new Enumeration[2];
 1031           if (parent != null) {
 1032               tmp[0] = parent.getResources(name);
 1033           } else {
 1034               tmp[0] = getBootstrapResources(name);
 1035           }
 1036           tmp[1] = findResources(name);
 1037   
 1038           return new CompoundEnumeration<URL>(tmp);
 1039       }
 1040   
 1041       /**
 1042        * Finds the resource with the given name. Class loader implementations
 1043        * should override this method to specify where to find resources.  </p>
 1044        *
 1045        * @param  name
 1046        *         The resource name
 1047        *
 1048        * @return  A <tt>URL</tt> object for reading the resource, or
 1049        *          <tt>null</tt> if the resource could not be found
 1050        *
 1051        * @since  1.2
 1052        */
 1053       protected URL findResource(String name) {
 1054           return null;
 1055       }
 1056   
 1057       /**
 1058        * Returns an enumeration of {@link java.net.URL <tt>URL</tt>} objects
 1059        * representing all the resources with the given name. Class loader
 1060        * implementations should override this method to specify where to load
 1061        * resources from.  </p>
 1062        *
 1063        * @param  name
 1064        *         The resource name
 1065        *
 1066        * @return  An enumeration of {@link java.net.URL <tt>URL</tt>} objects for
 1067        *          the resources
 1068        *
 1069        * @throws  IOException
 1070        *          If I/O errors occur
 1071        *
 1072        * @since  1.2
 1073        */
 1074       protected Enumeration<URL> findResources(String name) throws IOException {
 1075           return java.util.Collections.emptyEnumeration();
 1076       }
 1077   
 1078       /**
 1079        * Find a resource of the specified name from the search path used to load
 1080        * classes.  This method locates the resource through the system class
 1081        * loader (see {@link #getSystemClassLoader()}).  </p>
 1082        *
 1083        * @param  name
 1084        *         The resource name
 1085        *
 1086        * @return  A {@link java.net.URL <tt>URL</tt>} object for reading the
 1087        *          resource, or <tt>null</tt> if the resource could not be found
 1088        *
 1089        * @since  1.1
 1090        */
 1091       public static URL getSystemResource(String name) {
 1092           ClassLoader system = getSystemClassLoader();
 1093           if (system == null) {
 1094               return getBootstrapResource(name);
 1095           }
 1096           return system.getResource(name);
 1097       }
 1098   
 1099       /**
 1100        * Finds all resources of the specified name from the search path used to
 1101        * load classes.  The resources thus found are returned as an
 1102        * {@link java.util.Enumeration <tt>Enumeration</tt>} of {@link
 1103        * java.net.URL <tt>URL</tt>} objects.
 1104        *
 1105        * <p> The search order is described in the documentation for {@link
 1106        * #getSystemResource(String)}.  </p>
 1107        *
 1108        * @param  name
 1109        *         The resource name
 1110        *
 1111        * @return  An enumeration of resource {@link java.net.URL <tt>URL</tt>}
 1112        *          objects
 1113        *
 1114        * @throws  IOException
 1115        *          If I/O errors occur
 1116   
 1117        * @since  1.2
 1118        */
 1119       public static Enumeration<URL> getSystemResources(String name)
 1120           throws IOException
 1121       {
 1122           ClassLoader system = getSystemClassLoader();
 1123           if (system == null) {
 1124               return getBootstrapResources(name);
 1125           }
 1126           return system.getResources(name);
 1127       }
 1128   
 1129       /**
 1130        * Find resources from the VM's built-in classloader.
 1131        */
 1132       private static URL getBootstrapResource(String name) {
 1133           URLClassPath ucp = getBootstrapClassPath();
 1134           Resource res = ucp.getResource(name);
 1135           return res != null ? res.getURL() : null;
 1136       }
 1137   
 1138       /**
 1139        * Find resources from the VM's built-in classloader.
 1140        */
 1141       private static Enumeration<URL> getBootstrapResources(String name)
 1142           throws IOException
 1143       {
 1144           final Enumeration<Resource> e = getBootstrapClassPath().getResources(name);
 1145           return new Enumeration<URL> () {
 1146               public URL nextElement() {
 1147                   return e.nextElement().getURL();
 1148               }
 1149               public boolean hasMoreElements() {
 1150                   return e.hasMoreElements();
 1151               }
 1152           };
 1153       }
 1154   
 1155       // Returns the URLClassPath that is used for finding system resources.
 1156       static URLClassPath getBootstrapClassPath() {
 1157           if (bootstrapClassPath == null) {
 1158               bootstrapClassPath = sun.misc.Launcher.getBootstrapClassPath();
 1159           }
 1160           return bootstrapClassPath;
 1161       }
 1162   
 1163       private static URLClassPath bootstrapClassPath;
 1164   
 1165       /**
 1166        * Returns an input stream for reading the specified resource.
 1167        *
 1168        * <p> The search order is described in the documentation for {@link
 1169        * #getResource(String)}.  </p>
 1170        *
 1171        * @param  name
 1172        *         The resource name
 1173        *
 1174        * @return  An input stream for reading the resource, or <tt>null</tt>
 1175        *          if the resource could not be found
 1176        *
 1177        * @since  1.1
 1178        */
 1179       public InputStream getResourceAsStream(String name) {
 1180           URL url = getResource(name);
 1181           try {
 1182               return url != null ? url.openStream() : null;
 1183           } catch (IOException e) {
 1184               return null;
 1185           }
 1186       }
 1187   
 1188       /**
 1189        * Open for reading, a resource of the specified name from the search path
 1190        * used to load classes.  This method locates the resource through the
 1191        * system class loader (see {@link #getSystemClassLoader()}).  </p>
 1192        *
 1193        * @param  name
 1194        *         The resource name
 1195        *
 1196        * @return  An input stream for reading the resource, or <tt>null</tt>
 1197        *          if the resource could not be found
 1198        *
 1199        * @since  1.1
 1200        */
 1201       public static InputStream getSystemResourceAsStream(String name) {
 1202           URL url = getSystemResource(name);
 1203           try {
 1204               return url != null ? url.openStream() : null;
 1205           } catch (IOException e) {
 1206               return null;
 1207           }
 1208       }
 1209   
 1210   
 1211       // -- Hierarchy --
 1212   
 1213       /**
 1214        * Returns the parent class loader for delegation. Some implementations may
 1215        * use <tt>null</tt> to represent the bootstrap class loader. This method
 1216        * will return <tt>null</tt> in such implementations if this class loader's
 1217        * parent is the bootstrap class loader.
 1218        *
 1219        * <p> If a security manager is present, and the invoker's class loader is
 1220        * not <tt>null</tt> and is not an ancestor of this class loader, then this
 1221        * method invokes the security manager's {@link
 1222        * SecurityManager#checkPermission(java.security.Permission)
 1223        * <tt>checkPermission</tt>} method with a {@link
 1224        * RuntimePermission#RuntimePermission(String)
 1225        * <tt>RuntimePermission("getClassLoader")</tt>} permission to verify
 1226        * access to the parent class loader is permitted.  If not, a
 1227        * <tt>SecurityException</tt> will be thrown.  </p>
 1228        *
 1229        * @return  The parent <tt>ClassLoader</tt>
 1230        *
 1231        * @throws  SecurityException
 1232        *          If a security manager exists and its <tt>checkPermission</tt>
 1233        *          method doesn't allow access to this class loader's parent class
 1234        *          loader.
 1235        *
 1236        * @since  1.2
 1237        */
 1238       public final ClassLoader getParent() {
 1239           if (parent == null)
 1240               return null;
 1241           SecurityManager sm = System.getSecurityManager();
 1242           if (sm != null) {
 1243               ClassLoader ccl = getCallerClassLoader();
 1244               if (ccl != null && !isAncestor(ccl)) {
 1245                   sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
 1246               }
 1247           }
 1248           return parent;
 1249       }
 1250   
 1251       /**
 1252        * Returns the system class loader for delegation.  This is the default
 1253        * delegation parent for new <tt>ClassLoader</tt> instances, and is
 1254        * typically the class loader used to start the application.
 1255        *
 1256        * <p> This method is first invoked early in the runtime's startup
 1257        * sequence, at which point it creates the system class loader and sets it
 1258        * as the context class loader of the invoking <tt>Thread</tt>.
 1259        *
 1260        * <p> The default system class loader is an implementation-dependent
 1261        * instance of this class.
 1262        *
 1263        * <p> If the system property "<tt>java.system.class.loader</tt>" is defined
 1264        * when this method is first invoked then the value of that property is
 1265        * taken to be the name of a class that will be returned as the system
 1266        * class loader.  The class is loaded using the default system class loader
 1267        * and must define a public constructor that takes a single parameter of
 1268        * type <tt>ClassLoader</tt> which is used as the delegation parent.  An
 1269        * instance is then created using this constructor with the default system
 1270        * class loader as the parameter.  The resulting class loader is defined
 1271        * to be the system class loader.
 1272        *
 1273        * <p> If a security manager is present, and the invoker's class loader is
 1274        * not <tt>null</tt> and the invoker's class loader is not the same as or
 1275        * an ancestor of the system class loader, then this method invokes the
 1276        * security manager's {@link
 1277        * SecurityManager#checkPermission(java.security.Permission)
 1278        * <tt>checkPermission</tt>} method with a {@link
 1279        * RuntimePermission#RuntimePermission(String)
 1280        * <tt>RuntimePermission("getClassLoader")</tt>} permission to verify
 1281        * access to the system class loader.  If not, a
 1282        * <tt>SecurityException</tt> will be thrown.  </p>
 1283        *
 1284        * @return  The system <tt>ClassLoader</tt> for delegation, or
 1285        *          <tt>null</tt> if none
 1286        *
 1287        * @throws  SecurityException
 1288        *          If a security manager exists and its <tt>checkPermission</tt>
 1289        *          method doesn't allow access to the system class loader.
 1290        *
 1291        * @throws  IllegalStateException
 1292        *          If invoked recursively during the construction of the class
 1293        *          loader specified by the "<tt>java.system.class.loader</tt>"
 1294        *          property.
 1295        *
 1296        * @throws  Error
 1297        *          If the system property "<tt>java.system.class.loader</tt>"
 1298        *          is defined but the named class could not be loaded, the
 1299        *          provider class does not define the required constructor, or an
 1300        *          exception is thrown by that constructor when it is invoked. The
 1301        *          underlying cause of the error can be retrieved via the
 1302        *          {@link Throwable#getCause()} method.
 1303        *
 1304        * @revised  1.4
 1305        */
 1306       public static ClassLoader getSystemClassLoader() {
 1307           initSystemClassLoader();
 1308           if (scl == null) {
 1309               return null;
 1310           }
 1311           SecurityManager sm = System.getSecurityManager();
 1312           if (sm != null) {
 1313               ClassLoader ccl = getCallerClassLoader();
 1314               if (ccl != null && ccl != scl && !scl.isAncestor(ccl)) {
 1315                   sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
 1316               }
 1317           }
 1318           return scl;
 1319       }
 1320   
 1321       private static synchronized void initSystemClassLoader() {
 1322           if (!sclSet) {
 1323               if (scl != null)
 1324                   throw new IllegalStateException("recursive invocation");
 1325               sun.misc.Launcher l = sun.misc.Launcher.getLauncher();
 1326               if (l != null) {
 1327                   Throwable oops = null;
 1328                   scl = l.getClassLoader();
 1329                   try {
 1330                       scl = AccessController.doPrivileged(
 1331                           new SystemClassLoaderAction(scl));
 1332                   } catch (PrivilegedActionException pae) {
 1333                       oops = pae.getCause();
 1334                       if (oops instanceof InvocationTargetException) {
 1335                           oops = oops.getCause();
 1336                       }
 1337                   }
 1338                   if (oops != null) {
 1339                       if (oops instanceof Error) {
 1340                           throw (Error) oops;
 1341                       } else {
 1342                           // wrap the exception
 1343                           throw new Error(oops);
 1344                       }
 1345                   }
 1346               }
 1347               sclSet = true;
 1348           }
 1349       }
 1350   
 1351       // Returns true if the specified class loader can be found in this class
 1352       // loader's delegation chain.
 1353       boolean isAncestor(ClassLoader cl) {
 1354           ClassLoader acl = this;
 1355           do {
 1356               acl = acl.parent;
 1357               if (cl == acl) {
 1358                   return true;
 1359               }
 1360           } while (acl != null);
 1361           return false;
 1362       }
 1363   
 1364       // Returns the invoker's class loader, or null if none.
 1365       // NOTE: This must always be invoked when there is exactly one intervening
 1366       // frame from the core libraries on the stack between this method's
 1367       // invocation and the desired invoker.
 1368       static ClassLoader getCallerClassLoader() {
 1369           // NOTE use of more generic Reflection.getCallerClass()
 1370           Class caller = Reflection.getCallerClass(3);
 1371           // This can be null if the VM is requesting it
 1372           if (caller == null) {
 1373               return null;
 1374           }
 1375           // Circumvent security check since this is package-private
 1376           return caller.getClassLoader0();
 1377       }
 1378   
 1379       // The class loader for the system
 1380       private static ClassLoader scl;
 1381   
 1382       // Set to true once the system class loader has been set
 1383       private static boolean sclSet;
 1384   
 1385   
 1386       // -- Package --
 1387   
 1388       /**
 1389        * Defines a package by name in this <tt>ClassLoader</tt>.  This allows
 1390        * class loaders to define the packages for their classes. Packages must
 1391        * be created before the class is defined, and package names must be
 1392        * unique within a class loader and cannot be redefined or changed once
 1393        * created.  </p>
 1394        *
 1395        * @param  name
 1396        *         The package name
 1397        *
 1398        * @param  specTitle
 1399        *         The specification title
 1400        *
 1401        * @param  specVersion
 1402        *         The specification version
 1403        *
 1404        * @param  specVendor
 1405        *         The specification vendor
 1406        *
 1407        * @param  implTitle
 1408        *         The implementation title
 1409        *
 1410        * @param  implVersion
 1411        *         The implementation version
 1412        *
 1413        * @param  implVendor
 1414        *         The implementation vendor
 1415        *
 1416        * @param  sealBase
 1417        *         If not <tt>null</tt>, then this package is sealed with
 1418        *         respect to the given code source {@link java.net.URL
 1419        *         <tt>URL</tt>}  object.  Otherwise, the package is not sealed.
 1420        *
 1421        * @return  The newly defined <tt>Package</tt> object
 1422        *
 1423        * @throws  IllegalArgumentException
 1424        *          If package name duplicates an existing package either in this
 1425        *          class loader or one of its ancestors
 1426        *
 1427        * @since  1.2
 1428        */
 1429       protected Package definePackage(String name, String specTitle,
 1430                                       String specVersion, String specVendor,
 1431                                       String implTitle, String implVersion,
 1432                                       String implVendor, URL sealBase)
 1433           throws IllegalArgumentException
 1434       {
 1435           synchronized (packages) {
 1436               Package pkg = getPackage(name);
 1437               if (pkg != null) {
 1438                   throw new IllegalArgumentException(name);
 1439               }
 1440               pkg = new Package(name, specTitle, specVersion, specVendor,
 1441                                 implTitle, implVersion, implVendor,
 1442                                 sealBase, this);
 1443               packages.put(name, pkg);
 1444               return pkg;
 1445           }
 1446       }
 1447   
 1448       /**
 1449        * Returns a <tt>Package</tt> that has been defined by this class loader
 1450        * or any of its ancestors.  </p>
 1451        *
 1452        * @param  name
 1453        *         The package name
 1454        *
 1455        * @return  The <tt>Package</tt> corresponding to the given name, or
 1456        *          <tt>null</tt> if not found
 1457        *
 1458        * @since  1.2
 1459        */
 1460       protected Package getPackage(String name) {
 1461           synchronized (packages) {
 1462               Package pkg = packages.get(name);
 1463               if (pkg == null) {
 1464                   if (parent != null) {
 1465                       pkg = parent.getPackage(name);
 1466                   } else {
 1467                       pkg = Package.getSystemPackage(name);
 1468                   }
 1469                   if (pkg != null) {
 1470                       packages.put(name, pkg);
 1471                   }
 1472               }
 1473               return pkg;
 1474           }
 1475       }
 1476   
 1477       /**
 1478        * Returns all of the <tt>Packages</tt> defined by this class loader and
 1479        * its ancestors.  </p>
 1480        *
 1481        * @return  The array of <tt>Package</tt> objects defined by this
 1482        *          <tt>ClassLoader</tt>
 1483        *
 1484        * @since  1.2
 1485        */
 1486       protected Package[] getPackages() {
 1487           Map<String, Package> map;
 1488           synchronized (packages) {
 1489               map = new HashMap<String, Package>(packages);
 1490           }
 1491           Package[] pkgs;
 1492           if (parent != null) {
 1493               pkgs = parent.getPackages();
 1494           } else {
 1495               pkgs = Package.getSystemPackages();
 1496           }
 1497           if (pkgs != null) {
 1498               for (int i = 0; i < pkgs.length; i++) {
 1499                   String pkgName = pkgs[i].getName();
 1500                   if (map.get(pkgName) == null) {
 1501                       map.put(pkgName, pkgs[i]);
 1502                   }
 1503               }
 1504           }
 1505           return map.values().toArray(new Package[map.size()]);
 1506       }
 1507   
 1508   
 1509       // -- Native library access --
 1510   
 1511       /**
 1512        * Returns the absolute path name of a native library.  The VM invokes this
 1513        * method to locate the native libraries that belong to classes loaded with
 1514        * this class loader. If this method returns <tt>null</tt>, the VM
 1515        * searches the library along the path specified as the
 1516        * "<tt>java.library.path</tt>" property.  </p>
 1517        *
 1518        * @param  libname
 1519        *         The library name
 1520        *
 1521        * @return  The absolute path of the native library
 1522        *
 1523        * @see  System#loadLibrary(String)
 1524        * @see  System#mapLibraryName(String)
 1525        *
 1526        * @since  1.2
 1527        */
 1528       protected String findLibrary(String libname) {
 1529           return null;
 1530       }
 1531   
 1532       /**
 1533        * The inner class NativeLibrary denotes a loaded native library instance.
 1534        * Every classloader contains a vector of loaded native libraries in the
 1535        * private field <tt>nativeLibraries</tt>.  The native libraries loaded
 1536        * into the system are entered into the <tt>systemNativeLibraries</tt>
 1537        * vector.
 1538        *
 1539        * <p> Every native library requires a particular version of JNI. This is
 1540        * denoted by the private <tt>jniVersion</tt> field.  This field is set by
 1541        * the VM when it loads the library, and used by the VM to pass the correct
 1542        * version of JNI to the native methods.  </p>
 1543        *
 1544        * @see      ClassLoader
 1545        * @since    1.2
 1546        */
 1547       static class NativeLibrary {
 1548           // opaque handle to native library, used in native code.
 1549           long handle;
 1550           // the version of JNI environment the native library requires.
 1551           private int jniVersion;
 1552           // the class from which the library is loaded, also indicates
 1553           // the loader this native library belongs.
 1554           private Class fromClass;
 1555           // the canonicalized name of the native library.
 1556           String name;
 1557   
 1558           native void load(String name);
 1559           native long find(String name);
 1560           native void unload();
 1561   
 1562           public NativeLibrary(Class fromClass, String name) {
 1563               this.name = name;
 1564               this.fromClass = fromClass;
 1565           }
 1566   
 1567           protected void finalize() {
 1568               synchronized (loadedLibraryNames) {
 1569                   if (fromClass.getClassLoader() != null && handle != 0) {
 1570                       /* remove the native library name */
 1571                       int size = loadedLibraryNames.size();
 1572                       for (int i = 0; i < size; i++) {
 1573                           if (name.equals(loadedLibraryNames.elementAt(i))) {
 1574                               loadedLibraryNames.removeElementAt(i);
 1575                               break;
 1576                           }
 1577                       }
 1578                       /* unload the library. */
 1579                       ClassLoader.nativeLibraryContext.push(this);
 1580                       try {
 1581                           unload();
 1582                       } finally {
 1583                           ClassLoader.nativeLibraryContext.pop();
 1584                       }
 1585                   }
 1586               }
 1587           }
 1588           // Invoked in the VM to determine the context class in
 1589           // JNI_Load/JNI_Unload
 1590           static Class getFromClass() {
 1591               return ClassLoader.nativeLibraryContext.peek().fromClass;
 1592           }
 1593       }
 1594   
 1595       // The "default" domain. Set as the default ProtectionDomain on newly
 1596       // created classes.
 1597       private ProtectionDomain defaultDomain = null;
 1598   
 1599       // Returns (and initializes) the default domain.
 1600       private synchronized ProtectionDomain getDefaultDomain() {
 1601           if (defaultDomain == null) {
 1602               CodeSource cs = new CodeSource(null, (Certificate[]) null);
 1603               defaultDomain = new ProtectionDomain(cs, null, this, null);
 1604           }
 1605           return defaultDomain;
 1606       }
 1607   
 1608       // All native library names we've loaded.
 1609       private static Vector<String> loadedLibraryNames
 1610           = new Vector<String>();
 1611   
 1612       // Native libraries belonging to system classes.
 1613       private static Vector<NativeLibrary> systemNativeLibraries
 1614           = new Vector<NativeLibrary>();
 1615   
 1616       // Native libraries associated with the class loader.
 1617       private Vector<NativeLibrary> nativeLibraries
 1618           = new Vector<NativeLibrary>();
 1619   
 1620       // native libraries being loaded/unloaded.
 1621       private static Stack<NativeLibrary> nativeLibraryContext
 1622           = new Stack<NativeLibrary>();
 1623   
 1624       // The paths searched for libraries
 1625       static private String usr_paths[];
 1626       static private String sys_paths[];
 1627   
 1628       private static String[] initializePath(String propname) {
 1629           String ldpath = System.getProperty(propname, "");
 1630           String ps = File.pathSeparator;
 1631           int ldlen = ldpath.length();
 1632           int i, j, n;
 1633           // Count the separators in the path
 1634           i = ldpath.indexOf(ps);
 1635           n = 0;
 1636           while (i >= 0) {
 1637               n++;
 1638               i = ldpath.indexOf(ps, i + 1);
 1639           }
 1640   
 1641           // allocate the array of paths - n :'s = n + 1 path elements
 1642           String[] paths = new String[n + 1];
 1643   
 1644           // Fill the array with paths from the ldpath
 1645           n = i = 0;
 1646           j = ldpath.indexOf(ps);
 1647           while (j >= 0) {
 1648               if (j - i > 0) {
 1649                   paths[n++] = ldpath.substring(i, j);
 1650               } else if (j - i == 0) {
 1651                   paths[n++] = ".";
 1652               }
 1653               i = j + 1;
 1654               j = ldpath.indexOf(ps, i);
 1655           }
 1656           paths[n] = ldpath.substring(i, ldlen);
 1657           return paths;
 1658       }
 1659   
 1660       // Invoked in the java.lang.Runtime class to implement load and loadLibrary.
 1661       static void loadLibrary(Class fromClass, String name,
 1662                               boolean isAbsolute) {
 1663           ClassLoader loader =
 1664               (fromClass == null) ? null : fromClass.getClassLoader();
 1665           if (sys_paths == null) {
 1666               usr_paths = initializePath("java.library.path");
 1667               sys_paths = initializePath("sun.boot.library.path");
 1668           }
 1669           if (isAbsolute) {
 1670               if (loadLibrary0(fromClass, new File(name))) {
 1671                   return;
 1672               }
 1673               throw new UnsatisfiedLinkError("Can't load library: " + name);
 1674           }
 1675           if (loader != null) {
 1676               String libfilename = loader.findLibrary(name);
 1677               if (libfilename != null) {
 1678                   File libfile = new File(libfilename);
 1679                   if (!libfile.isAbsolute()) {
 1680                       throw new UnsatisfiedLinkError(
 1681       "ClassLoader.findLibrary failed to return an absolute path: " + libfilename);
 1682                   }
 1683                   if (loadLibrary0(fromClass, libfile)) {
 1684                       return;
 1685                   }
 1686                   throw new UnsatisfiedLinkError("Can't load " + libfilename);
 1687               }
 1688           }
 1689           for (int i = 0 ; i < sys_paths.length ; i++) {
 1690               File libfile = new File(sys_paths[i], System.mapLibraryName(name));
 1691               if (loadLibrary0(fromClass, libfile)) {
 1692                   return;
 1693               }
 1694           }
 1695           if (loader != null) {
 1696               for (int i = 0 ; i < usr_paths.length ; i++) {
 1697                   File libfile = new File(usr_paths[i],
 1698                                           System.mapLibraryName(name));
 1699                   if (loadLibrary0(fromClass, libfile)) {
 1700                       return;
 1701                   }
 1702               }
 1703           }
 1704           // Oops, it failed
 1705           throw new UnsatisfiedLinkError("no " + name + " in java.library.path");
 1706       }
 1707   
 1708       private static boolean loadLibrary0(Class fromClass, final File file) {
 1709           boolean exists = AccessController.doPrivileged(
 1710               new PrivilegedAction<Object>() {
 1711                   public Object run() {
 1712                       return file.exists() ? Boolean.TRUE : null;
 1713                   }})
 1714               != null;
 1715           if (!exists) {
 1716               return false;
 1717           }
 1718           String name;
 1719           try {
 1720               name = file.getCanonicalPath();
 1721           } catch (IOException e) {
 1722               return false;
 1723           }
 1724           ClassLoader loader =
 1725               (fromClass == null) ? null : fromClass.getClassLoader();
 1726           Vector<NativeLibrary> libs =
 1727               loader != null ? loader.nativeLibraries : systemNativeLibraries;
 1728           synchronized (libs) {
 1729               int size = libs.size();
 1730               for (int i = 0; i < size; i++) {
 1731                   NativeLibrary lib = libs.elementAt(i);
 1732                   if (name.equals(lib.name)) {
 1733                       return true;
 1734                   }
 1735               }
 1736   
 1737               synchronized (loadedLibraryNames) {
 1738                   if (loadedLibraryNames.contains(name)) {
 1739                       throw new UnsatisfiedLinkError
 1740                           ("Native Library " +
 1741                            name +
 1742                            " already loaded in another classloader");
 1743                   }
 1744                   /* If the library is being loaded (must be by the same thread,
 1745                    * because Runtime.load and Runtime.loadLibrary are
 1746                    * synchronous). The reason is can occur is that the JNI_OnLoad
 1747                    * function can cause another loadLibrary invocation.
 1748                    *
 1749                    * Thus we can use a static stack to hold the list of libraries
 1750                    * we are loading.
 1751                    *
 1752                    * If there is a pending load operation for the library, we
 1753                    * immediately return success; otherwise, we raise
 1754                    * UnsatisfiedLinkError.
 1755                    */
 1756                   int n = nativeLibraryContext.size();
 1757                   for (int i = 0; i < n; i++) {
 1758                       NativeLibrary lib = nativeLibraryContext.elementAt(i);
 1759                       if (name.equals(lib.name)) {
 1760                           if (loader == lib.fromClass.getClassLoader()) {
 1761                               return true;
 1762                           } else {
 1763                               throw new UnsatisfiedLinkError
 1764                                   ("Native Library " +
 1765                                    name +
 1766                                    " is being loaded in another classloader");
 1767                           }
 1768                       }
 1769                   }
 1770                   NativeLibrary lib = new NativeLibrary(fromClass, name);
 1771                   nativeLibraryContext.push(lib);
 1772                   try {
 1773                       lib.load(name);
 1774                   } finally {
 1775                       nativeLibraryContext.pop();
 1776                   }
 1777                   if (lib.handle != 0) {
 1778                       loadedLibraryNames.addElement(name);
 1779                       libs.addElement(lib);
 1780                       return true;
 1781                   }
 1782                   return false;
 1783               }
 1784           }
 1785       }
 1786   
 1787       // Invoked in the VM class linking code.
 1788       static long findNative(ClassLoader loader, String name) {
 1789           Vector<NativeLibrary> libs =
 1790               loader != null ? loader.nativeLibraries : systemNativeLibraries;
 1791           synchronized (libs) {
 1792               int size = libs.size();
 1793               for (int i = 0; i < size; i++) {
 1794                   NativeLibrary lib = libs.elementAt(i);
 1795                   long entry = lib.find(name);
 1796                   if (entry != 0)
 1797                       return entry;
 1798               }
 1799           }
 1800           return 0;
 1801       }
 1802   
 1803   
 1804       // -- Assertion management --
 1805   
 1806       // The default toggle for assertion checking.
 1807       private boolean defaultAssertionStatus = false;
 1808   
 1809       // Maps String packageName to Boolean package default assertion status Note
 1810       // that the default package is placed under a null map key.  If this field
 1811       // is null then we are delegating assertion status queries to the VM, i.e.,
 1812       // none of this ClassLoader's assertion status modification methods have
 1813       // been invoked.
 1814       private Map<String, Boolean> packageAssertionStatus = null;
 1815   
 1816       // Maps String fullyQualifiedClassName to Boolean assertionStatus If this
 1817       // field is null then we are delegating assertion status queries to the VM,
 1818       // i.e., none of this ClassLoader's assertion status modification methods
 1819       // have been invoked.
 1820       Map<String, Boolean> classAssertionStatus = null;
 1821   
 1822       /**
 1823        * Sets the default assertion status for this class loader.  This setting
 1824        * determines whether classes loaded by this class loader and initialized
 1825        * in the future will have assertions enabled or disabled by default.
 1826        * This setting may be overridden on a per-package or per-class basis by
 1827        * invoking {@link #setPackageAssertionStatus(String, boolean)} or {@link
 1828        * #setClassAssertionStatus(String, boolean)}.  </p>
 1829        *
 1830        * @param  enabled
 1831        *         <tt>true</tt> if classes loaded by this class loader will
 1832        *         henceforth have assertions enabled by default, <tt>false</tt>
 1833        *         if they will have assertions disabled by default.
 1834        *
 1835        * @since  1.4
 1836        */
 1837       public synchronized void setDefaultAssertionStatus(boolean enabled) {
 1838           if (classAssertionStatus == null)
 1839               initializeJavaAssertionMaps();
 1840   
 1841           defaultAssertionStatus = enabled;
 1842       }
 1843   
 1844       /**
 1845        * Sets the package default assertion status for the named package.  The
 1846        * package default assertion status determines the assertion status for
 1847        * classes initialized in the future that belong to the named package or
 1848        * any of its "subpackages".
 1849        *
 1850        * <p> A subpackage of a package named p is any package whose name begins
 1851        * with "<tt>p.</tt>".  For example, <tt>javax.swing.text</tt> is a
 1852        * subpackage of <tt>javax.swing</tt>, and both <tt>java.util</tt> and
 1853        * <tt>java.lang.reflect</tt> are subpackages of <tt>java</tt>.
 1854        *
 1855        * <p> In the event that multiple package defaults apply to a given class,
 1856        * the package default pertaining to the most specific package takes
 1857        * precedence over the others.  For example, if <tt>javax.lang</tt> and
 1858        * <tt>javax.lang.reflect</tt> both have package defaults associated with
 1859        * them, the latter package default applies to classes in
 1860        * <tt>javax.lang.reflect</tt>.
 1861        *
 1862        * <p> Package defaults take precedence over the class loader's default
 1863        * assertion status, and may be overridden on a per-class basis by invoking
 1864        * {@link #setClassAssertionStatus(String, boolean)}.  </p>
 1865        *
 1866        * @param  packageName
 1867        *         The name of the package whose package default assertion status
 1868        *         is to be set. A <tt>null</tt> value indicates the unnamed
 1869        *         package that is "current"
 1870        *         (<a href="http://java.sun.com/docs/books/jls/">Java Language
 1871        *         Specification</a>, section 7.4.2).
 1872        *
 1873        * @param  enabled
 1874        *         <tt>true</tt> if classes loaded by this classloader and
 1875        *         belonging to the named package or any of its subpackages will
 1876        *         have assertions enabled by default, <tt>false</tt> if they will
 1877        *         have assertions disabled by default.
 1878        *
 1879        * @since  1.4
 1880        */
 1881       public synchronized void setPackageAssertionStatus(String packageName,
 1882                                                          boolean enabled)
 1883       {
 1884           if (packageAssertionStatus == null)
 1885               initializeJavaAssertionMaps();
 1886   
 1887           packageAssertionStatus.put(packageName, enabled);
 1888       }
 1889   
 1890       /**
 1891        * Sets the desired assertion status for the named top-level class in this
 1892        * class loader and any nested classes contained therein.  This setting
 1893        * takes precedence over the class loader's default assertion status, and
 1894        * over any applicable per-package default.  This method has no effect if
 1895        * the named class has already been initialized.  (Once a class is
 1896        * initialized, its assertion status cannot change.)
 1897        *
 1898        * <p> If the named class is not a top-level class, this invocation will
 1899        * have no effect on the actual assertion status of any class. </p>
 1900        *
 1901        * @param  className
 1902        *         The fully qualified class name of the top-level class whose
 1903        *         assertion status is to be set.
 1904        *
 1905        * @param  enabled
 1906        *         <tt>true</tt> if the named class is to have assertions
 1907        *         enabled when (and if) it is initialized, <tt>false</tt> if the
 1908        *         class is to have assertions disabled.
 1909        *
 1910        * @since  1.4
 1911        */
 1912       public synchronized void setClassAssertionStatus(String className,
 1913                                                        boolean enabled)
 1914       {
 1915           if (classAssertionStatus == null)
 1916               initializeJavaAssertionMaps();
 1917   
 1918           classAssertionStatus.put(className, enabled);
 1919       }
 1920   
 1921       /**
 1922        * Sets the default assertion status for this class loader to
 1923        * <tt>false</tt> and discards any package defaults or class assertion
 1924        * status settings associated with the class loader.  This method is
 1925        * provided so that class loaders can be made to ignore any command line or
 1926        * persistent assertion status settings and "start with a clean slate."
 1927        * </p>
 1928        *
 1929        * @since  1.4
 1930        */
 1931       public synchronized void clearAssertionStatus() {
 1932           /*
 1933            * Whether or not "Java assertion maps" are initialized, set
 1934            * them to empty maps, effectively ignoring any present settings.
 1935            */
 1936           classAssertionStatus = new HashMap<String, Boolean>();
 1937           packageAssertionStatus = new HashMap<String, Boolean>();
 1938   
 1939           defaultAssertionStatus = false;
 1940       }
 1941   
 1942       /**
 1943        * Returns the assertion status that would be assigned to the specified
 1944        * class if it were to be initialized at the time this method is invoked.
 1945        * If the named class has had its assertion status set, the most recent
 1946        * setting will be returned; otherwise, if any package default assertion
 1947        * status pertains to this class, the most recent setting for the most
 1948        * specific pertinent package default assertion status is returned;
 1949        * otherwise, this class loader's default assertion status is returned.
 1950        * </p>
 1951        *
 1952        * @param  className
 1953        *         The fully qualified class name of the class whose desired
 1954        *         assertion status is being queried.
 1955        *
 1956        * @return  The desired assertion status of the specified class.
 1957        *
 1958        * @see  #setClassAssertionStatus(String, boolean)
 1959        * @see  #setPackageAssertionStatus(String, boolean)
 1960        * @see  #setDefaultAssertionStatus(boolean)
 1961        *
 1962        * @since  1.4
 1963        */
 1964       synchronized boolean desiredAssertionStatus(String className) {
 1965           Boolean result;
 1966   
 1967           // assert classAssertionStatus   != null;
 1968           // assert packageAssertionStatus != null;
 1969   
 1970           // Check for a class entry
 1971           result = classAssertionStatus.get(className);
 1972           if (result != null)
 1973               return result.booleanValue();
 1974   
 1975           // Check for most specific package entry
 1976           int dotIndex = className.lastIndexOf(".");
 1977           if (dotIndex < 0) { // default package
 1978               result = packageAssertionStatus.get(null);
 1979               if (result != null)
 1980                   return result.booleanValue();
 1981           }
 1982           while(dotIndex > 0) {
 1983               className = className.substring(0, dotIndex);
 1984               result = packageAssertionStatus.get(className);
 1985               if (result != null)
 1986                   return result.booleanValue();
 1987               dotIndex = className.lastIndexOf(".", dotIndex-1);
 1988           }
 1989   
 1990           // Return the classloader default
 1991           return defaultAssertionStatus;
 1992       }
 1993   
 1994       // Set up the assertions with information provided by the VM.
 1995       private void initializeJavaAssertionMaps() {
 1996           // assert Thread.holdsLock(this);
 1997   
 1998           classAssertionStatus = new HashMap<String, Boolean>();
 1999           packageAssertionStatus = new HashMap<String, Boolean>();
 2000           AssertionStatusDirectives directives = retrieveDirectives();
 2001   
 2002           for(int i = 0; i < directives.classes.length; i++)
 2003               classAssertionStatus.put(directives.classes[i],
 2004                                        directives.classEnabled[i]);
 2005   
 2006           for(int i = 0; i < directives.packages.length; i++)
 2007               packageAssertionStatus.put(directives.packages[i],
 2008                                          directives.packageEnabled[i]);
 2009   
 2010           defaultAssertionStatus = directives.deflt;
 2011       }
 2012   
 2013       // Retrieves the assertion directives from the VM.
 2014       private static native AssertionStatusDirectives retrieveDirectives();
 2015   }
 2016   
 2017   
 2018   class SystemClassLoaderAction
 2019       implements PrivilegedExceptionAction<ClassLoader> {
 2020       private ClassLoader parent;
 2021   
 2022       SystemClassLoaderAction(ClassLoader parent) {
 2023           this.parent = parent;
 2024       }
 2025   
 2026       public ClassLoader run() throws Exception {
 2027           String cls = System.getProperty("java.system.class.loader");
 2028           if (cls == null) {
 2029               return parent;
 2030           }
 2031   
 2032           Constructor ctor = Class.forName(cls, true, parent)
 2033               .getDeclaredConstructor(new Class[] { ClassLoader.class });
 2034           ClassLoader sys = (ClassLoader) ctor.newInstance(
 2035               new Object[] { parent });
 2036           Thread.currentThread().setContextClassLoader(sys);
 2037           return sys;
 2038       }
 2039   }

Save This Page
Home » openjdk-7 » java » lang » [javadoc | source]