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