History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/lang/ClassLoader.java (1 of 18352 files). Show all

Unified · Split

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