1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/emul/src/main/java/java/io/Closeable.java Tue Oct 30 08:27:04 2012 +0100
1.3 @@ -0,0 +1,48 @@
1.4 +/*
1.5 + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1.7 + *
1.8 + * This code is free software; you can redistribute it and/or modify it
1.9 + * under the terms of the GNU General Public License version 2 only, as
1.10 + * published by the Free Software Foundation. Oracle designates this
1.11 + * particular file as subject to the "Classpath" exception as provided
1.12 + * by Oracle in the LICENSE file that accompanied this code.
1.13 + *
1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1.17 + * version 2 for more details (a copy is included in the LICENSE file that
1.18 + * accompanied this code).
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License version
1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1.23 + *
1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1.25 + * or visit www.oracle.com if you need additional information or have any
1.26 + * questions.
1.27 + */
1.28 +
1.29 +package java.io;
1.30 +
1.31 +import java.io.IOException;
1.32 +
1.33 +/**
1.34 + * A {@code Closeable} is a source or destination of data that can be closed.
1.35 + * The close method is invoked to release resources that the object is
1.36 + * holding (such as open files).
1.37 + *
1.38 + * @since 1.5
1.39 + */
1.40 +
1.41 +public interface Closeable extends AutoCloseable {
1.42 +
1.43 + /**
1.44 + * Closes this stream and releases any system resources associated
1.45 + * with it. If the stream is already closed then invoking this
1.46 + * method has no effect.
1.47 + *
1.48 + * @throws IOException if an I/O error occurs
1.49 + */
1.50 + public void close() throws IOException;
1.51 +}
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/emul/src/main/java/java/lang/AutoCloseable.java Tue Oct 30 08:27:04 2012 +0100
2.3 @@ -0,0 +1,72 @@
2.4 +/*
2.5 + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
2.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
2.7 + *
2.8 + * This code is free software; you can redistribute it and/or modify it
2.9 + * under the terms of the GNU General Public License version 2 only, as
2.10 + * published by the Free Software Foundation. Oracle designates this
2.11 + * particular file as subject to the "Classpath" exception as provided
2.12 + * by Oracle in the LICENSE file that accompanied this code.
2.13 + *
2.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
2.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
2.17 + * version 2 for more details (a copy is included in the LICENSE file that
2.18 + * accompanied this code).
2.19 + *
2.20 + * You should have received a copy of the GNU General Public License version
2.21 + * 2 along with this work; if not, write to the Free Software Foundation,
2.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2.23 + *
2.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2.25 + * or visit www.oracle.com if you need additional information or have any
2.26 + * questions.
2.27 + */
2.28 +
2.29 +package java.lang;
2.30 +
2.31 +/**
2.32 + * A resource that must be closed when it is no longer needed.
2.33 + *
2.34 + * @author Josh Bloch
2.35 + * @since 1.7
2.36 + */
2.37 +public interface AutoCloseable {
2.38 + /**
2.39 + * Closes this resource, relinquishing any underlying resources.
2.40 + * This method is invoked automatically on objects managed by the
2.41 + * {@code try}-with-resources statement.
2.42 + *
2.43 + * <p>While this interface method is declared to throw {@code
2.44 + * Exception}, implementers are <em>strongly</em> encouraged to
2.45 + * declare concrete implementations of the {@code close} method to
2.46 + * throw more specific exceptions, or to throw no exception at all
2.47 + * if the close operation cannot fail.
2.48 + *
2.49 + * <p><em>Implementers of this interface are also strongly advised
2.50 + * to not have the {@code close} method throw {@link
2.51 + * InterruptedException}.</em>
2.52 + *
2.53 + * This exception interacts with a thread's interrupted status,
2.54 + * and runtime misbehavior is likely to occur if an {@code
2.55 + * InterruptedException} is {@linkplain Throwable#addSuppressed
2.56 + * suppressed}.
2.57 + *
2.58 + * More generally, if it would cause problems for an
2.59 + * exception to be suppressed, the {@code AutoCloseable.close}
2.60 + * method should not throw it.
2.61 + *
2.62 + * <p>Note that unlike the {@link java.io.Closeable#close close}
2.63 + * method of {@link java.io.Closeable}, this {@code close} method
2.64 + * is <em>not</em> required to be idempotent. In other words,
2.65 + * calling this {@code close} method more than once may have some
2.66 + * visible side effect, unlike {@code Closeable.close} which is
2.67 + * required to have no effect if called more than once.
2.68 + *
2.69 + * However, implementers of this interface are strongly encouraged
2.70 + * to make their {@code close} methods idempotent.
2.71 + *
2.72 + * @throws Exception if this resource cannot be closed
2.73 + */
2.74 + void close() throws Exception;
2.75 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/emul/src/main/java/java/lang/ClassLoader.java Tue Oct 30 08:27:04 2012 +0100
3.3 @@ -0,0 +1,2204 @@
3.4 +/*
3.5 + * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3.7 + *
3.8 + * This code is free software; you can redistribute it and/or modify it
3.9 + * under the terms of the GNU General Public License version 2 only, as
3.10 + * published by the Free Software Foundation. Oracle designates this
3.11 + * particular file as subject to the "Classpath" exception as provided
3.12 + * by Oracle in the LICENSE file that accompanied this code.
3.13 + *
3.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
3.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
3.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
3.17 + * version 2 for more details (a copy is included in the LICENSE file that
3.18 + * accompanied this code).
3.19 + *
3.20 + * You should have received a copy of the GNU General Public License version
3.21 + * 2 along with this work; if not, write to the Free Software Foundation,
3.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
3.23 + *
3.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
3.25 + * or visit www.oracle.com if you need additional information or have any
3.26 + * questions.
3.27 + */
3.28 +package java.lang;
3.29 +
3.30 +import java.io.InputStream;
3.31 +import java.io.IOException;
3.32 +import java.io.File;
3.33 +import java.lang.reflect.Constructor;
3.34 +import java.lang.reflect.InvocationTargetException;
3.35 +import java.net.MalformedURLException;
3.36 +import java.net.URL;
3.37 +import java.security.AccessController;
3.38 +import java.security.AccessControlContext;
3.39 +import java.security.CodeSource;
3.40 +import java.security.Policy;
3.41 +import java.security.PrivilegedAction;
3.42 +import java.security.PrivilegedActionException;
3.43 +import java.security.PrivilegedExceptionAction;
3.44 +import java.security.ProtectionDomain;
3.45 +import java.security.cert.Certificate;
3.46 +import java.util.Collections;
3.47 +import java.util.Enumeration;
3.48 +import java.util.HashMap;
3.49 +import java.util.HashSet;
3.50 +import java.util.Set;
3.51 +import java.util.Stack;
3.52 +import java.util.Map;
3.53 +import java.util.Vector;
3.54 +import java.util.Hashtable;
3.55 +import java.util.WeakHashMap;
3.56 +import java.util.concurrent.ConcurrentHashMap;
3.57 +import sun.misc.ClassFileTransformer;
3.58 +import sun.misc.CompoundEnumeration;
3.59 +import sun.misc.Resource;
3.60 +import sun.misc.URLClassPath;
3.61 +import sun.misc.VM;
3.62 +import sun.reflect.Reflection;
3.63 +import sun.security.util.SecurityConstants;
3.64 +
3.65 +/**
3.66 + * A class loader is an object that is responsible for loading classes. The
3.67 + * class <tt>ClassLoader</tt> is an abstract class. Given the <a
3.68 + * href="#name">binary name</a> of a class, a class loader should attempt to
3.69 + * locate or generate data that constitutes a definition for the class. A
3.70 + * typical strategy is to transform the name into a file name and then read a
3.71 + * "class file" of that name from a file system.
3.72 + *
3.73 + * <p> Every {@link Class <tt>Class</tt>} object contains a {@link
3.74 + * Class#getClassLoader() reference} to the <tt>ClassLoader</tt> that defined
3.75 + * it.
3.76 + *
3.77 + * <p> <tt>Class</tt> objects for array classes are not created by class
3.78 + * loaders, but are created automatically as required by the Java runtime.
3.79 + * The class loader for an array class, as returned by {@link
3.80 + * Class#getClassLoader()} is the same as the class loader for its element
3.81 + * type; if the element type is a primitive type, then the array class has no
3.82 + * class loader.
3.83 + *
3.84 + * <p> Applications implement subclasses of <tt>ClassLoader</tt> in order to
3.85 + * extend the manner in which the Java virtual machine dynamically loads
3.86 + * classes.
3.87 + *
3.88 + * <p> Class loaders may typically be used by security managers to indicate
3.89 + * security domains.
3.90 + *
3.91 + * <p> The <tt>ClassLoader</tt> class uses a delegation model to search for
3.92 + * classes and resources. Each instance of <tt>ClassLoader</tt> has an
3.93 + * associated parent class loader. When requested to find a class or
3.94 + * resource, a <tt>ClassLoader</tt> instance will delegate the search for the
3.95 + * class or resource to its parent class loader before attempting to find the
3.96 + * class or resource itself. The virtual machine's built-in class loader,
3.97 + * called the "bootstrap class loader", does not itself have a parent but may
3.98 + * serve as the parent of a <tt>ClassLoader</tt> instance.
3.99 + *
3.100 + * <p> Class loaders that support concurrent loading of classes are known as
3.101 + * <em>parallel capable</em> class loaders and are required to register
3.102 + * themselves at their class initialization time by invoking the
3.103 + * {@link
3.104 + * #registerAsParallelCapable <tt>ClassLoader.registerAsParallelCapable</tt>}
3.105 + * method. Note that the <tt>ClassLoader</tt> class is registered as parallel
3.106 + * capable by default. However, its subclasses still need to register themselves
3.107 + * if they are parallel capable. <br>
3.108 + * In environments in which the delegation model is not strictly
3.109 + * hierarchical, class loaders need to be parallel capable, otherwise class
3.110 + * loading can lead to deadlocks because the loader lock is held for the
3.111 + * duration of the class loading process (see {@link #loadClass
3.112 + * <tt>loadClass</tt>} methods).
3.113 + *
3.114 + * <p> Normally, the Java virtual machine loads classes from the local file
3.115 + * system in a platform-dependent manner. For example, on UNIX systems, the
3.116 + * virtual machine loads classes from the directory defined by the
3.117 + * <tt>CLASSPATH</tt> environment variable.
3.118 + *
3.119 + * <p> However, some classes may not originate from a file; they may originate
3.120 + * from other sources, such as the network, or they could be constructed by an
3.121 + * application. The method {@link #defineClass(String, byte[], int, int)
3.122 + * <tt>defineClass</tt>} converts an array of bytes into an instance of class
3.123 + * <tt>Class</tt>. Instances of this newly defined class can be created using
3.124 + * {@link Class#newInstance <tt>Class.newInstance</tt>}.
3.125 + *
3.126 + * <p> The methods and constructors of objects created by a class loader may
3.127 + * reference other classes. To determine the class(es) referred to, the Java
3.128 + * virtual machine invokes the {@link #loadClass <tt>loadClass</tt>} method of
3.129 + * the class loader that originally created the class.
3.130 + *
3.131 + * <p> For example, an application could create a network class loader to
3.132 + * download class files from a server. Sample code might look like:
3.133 + *
3.134 + * <blockquote><pre>
3.135 + * ClassLoader loader = new NetworkClassLoader(host, port);
3.136 + * Object main = loader.loadClass("Main", true).newInstance();
3.137 + * . . .
3.138 + * </pre></blockquote>
3.139 + *
3.140 + * <p> The network class loader subclass must define the methods {@link
3.141 + * #findClass <tt>findClass</tt>} and <tt>loadClassData</tt> to load a class
3.142 + * from the network. Once it has downloaded the bytes that make up the class,
3.143 + * it should use the method {@link #defineClass <tt>defineClass</tt>} to
3.144 + * create a class instance. A sample implementation is:
3.145 + *
3.146 + * <blockquote><pre>
3.147 + * class NetworkClassLoader extends ClassLoader {
3.148 + * String host;
3.149 + * int port;
3.150 + *
3.151 + * public Class findClass(String name) {
3.152 + * byte[] b = loadClassData(name);
3.153 + * return defineClass(name, b, 0, b.length);
3.154 + * }
3.155 + *
3.156 + * private byte[] loadClassData(String name) {
3.157 + * // load the class data from the connection
3.158 + * . . .
3.159 + * }
3.160 + * }
3.161 + * </pre></blockquote>
3.162 + *
3.163 + * <h4> <a name="name">Binary names</a> </h4>
3.164 + *
3.165 + * <p> Any class name provided as a {@link String} parameter to methods in
3.166 + * <tt>ClassLoader</tt> must be a binary name as defined by
3.167 + * <cite>The Java™ Language Specification</cite>.
3.168 + *
3.169 + * <p> Examples of valid class names include:
3.170 + * <blockquote><pre>
3.171 + * "java.lang.String"
3.172 + * "javax.swing.JSpinner$DefaultEditor"
3.173 + * "java.security.KeyStore$Builder$FileBuilder$1"
3.174 + * "java.net.URLClassLoader$3$1"
3.175 + * </pre></blockquote>
3.176 + *
3.177 + * @see #resolveClass(Class)
3.178 + * @since 1.0
3.179 + */
3.180 +public abstract class ClassLoader {
3.181 +
3.182 + private static native void registerNatives();
3.183 + static {
3.184 + registerNatives();
3.185 + }
3.186 +
3.187 + // The parent class loader for delegation
3.188 + // Note: VM hardcoded the offset of this field, thus all new fields
3.189 + // must be added *after* it.
3.190 + private final ClassLoader parent;
3.191 +
3.192 + /**
3.193 + * Encapsulates the set of parallel capable loader types.
3.194 + */
3.195 + private static class ParallelLoaders {
3.196 + private ParallelLoaders() {}
3.197 +
3.198 + // the set of parallel capable loader types
3.199 + private static final Set<Class<? extends ClassLoader>> loaderTypes =
3.200 + Collections.newSetFromMap(
3.201 + new WeakHashMap<Class<? extends ClassLoader>, Boolean>());
3.202 + static {
3.203 + synchronized (loaderTypes) { loaderTypes.add(ClassLoader.class); }
3.204 + }
3.205 +
3.206 + /**
3.207 + * Registers the given class loader type as parallel capabale.
3.208 + * Returns {@code true} is successfully registered; {@code false} if
3.209 + * loader's super class is not registered.
3.210 + */
3.211 + static boolean register(Class<? extends ClassLoader> c) {
3.212 + synchronized (loaderTypes) {
3.213 + if (loaderTypes.contains(c.getSuperclass())) {
3.214 + // register the class loader as parallel capable
3.215 + // if and only if all of its super classes are.
3.216 + // Note: given current classloading sequence, if
3.217 + // the immediate super class is parallel capable,
3.218 + // all the super classes higher up must be too.
3.219 + loaderTypes.add(c);
3.220 + return true;
3.221 + } else {
3.222 + return false;
3.223 + }
3.224 + }
3.225 + }
3.226 +
3.227 + /**
3.228 + * Returns {@code true} if the given class loader type is
3.229 + * registered as parallel capable.
3.230 + */
3.231 + static boolean isRegistered(Class<? extends ClassLoader> c) {
3.232 + synchronized (loaderTypes) {
3.233 + return loaderTypes.contains(c);
3.234 + }
3.235 + }
3.236 + }
3.237 +
3.238 + // Maps class name to the corresponding lock object when the current
3.239 + // class loader is parallel capable.
3.240 + // Note: VM also uses this field to decide if the current class loader
3.241 + // is parallel capable and the appropriate lock object for class loading.
3.242 + private final ConcurrentHashMap<String, Object> parallelLockMap;
3.243 +
3.244 + // Hashtable that maps packages to certs
3.245 + private final Map <String, Certificate[]> package2certs;
3.246 +
3.247 + // Shared among all packages with unsigned classes
3.248 + private static final Certificate[] nocerts = new Certificate[0];
3.249 +
3.250 + // The classes loaded by this class loader. The only purpose of this table
3.251 + // is to keep the classes from being GC'ed until the loader is GC'ed.
3.252 + private final Vector<Class<?>> classes = new Vector<>();
3.253 +
3.254 + // The "default" domain. Set as the default ProtectionDomain on newly
3.255 + // created classes.
3.256 + private final ProtectionDomain defaultDomain =
3.257 + new ProtectionDomain(new CodeSource(null, (Certificate[]) null),
3.258 + null, this, null);
3.259 +
3.260 + // The initiating protection domains for all classes loaded by this loader
3.261 + private final Set<ProtectionDomain> domains;
3.262 +
3.263 + // Invoked by the VM to record every loaded class with this loader.
3.264 + void addClass(Class c) {
3.265 + classes.addElement(c);
3.266 + }
3.267 +
3.268 + // The packages defined in this class loader. Each package name is mapped
3.269 + // to its corresponding Package object.
3.270 + // @GuardedBy("itself")
3.271 + private final HashMap<String, Package> packages = new HashMap<>();
3.272 +
3.273 + private static Void checkCreateClassLoader() {
3.274 + SecurityManager security = System.getSecurityManager();
3.275 + if (security != null) {
3.276 + security.checkCreateClassLoader();
3.277 + }
3.278 + return null;
3.279 + }
3.280 +
3.281 + private ClassLoader(Void unused, ClassLoader parent) {
3.282 + this.parent = parent;
3.283 + if (ParallelLoaders.isRegistered(this.getClass())) {
3.284 + parallelLockMap = new ConcurrentHashMap<>();
3.285 + package2certs = new ConcurrentHashMap<>();
3.286 + domains =
3.287 + Collections.synchronizedSet(new HashSet<ProtectionDomain>());
3.288 + assertionLock = new Object();
3.289 + } else {
3.290 + // no finer-grained lock; lock on the classloader instance
3.291 + parallelLockMap = null;
3.292 + package2certs = new Hashtable<>();
3.293 + domains = new HashSet<>();
3.294 + assertionLock = this;
3.295 + }
3.296 + }
3.297 +
3.298 + /**
3.299 + * Creates a new class loader using the specified parent class loader for
3.300 + * delegation.
3.301 + *
3.302 + * <p> If there is a security manager, its {@link
3.303 + * SecurityManager#checkCreateClassLoader()
3.304 + * <tt>checkCreateClassLoader</tt>} method is invoked. This may result in
3.305 + * a security exception. </p>
3.306 + *
3.307 + * @param parent
3.308 + * The parent class loader
3.309 + *
3.310 + * @throws SecurityException
3.311 + * If a security manager exists and its
3.312 + * <tt>checkCreateClassLoader</tt> method doesn't allow creation
3.313 + * of a new class loader.
3.314 + *
3.315 + * @since 1.2
3.316 + */
3.317 + protected ClassLoader(ClassLoader parent) {
3.318 + this(checkCreateClassLoader(), parent);
3.319 + }
3.320 +
3.321 + /**
3.322 + * Creates a new class loader using the <tt>ClassLoader</tt> returned by
3.323 + * the method {@link #getSystemClassLoader()
3.324 + * <tt>getSystemClassLoader()</tt>} as the parent class loader.
3.325 + *
3.326 + * <p> If there is a security manager, its {@link
3.327 + * SecurityManager#checkCreateClassLoader()
3.328 + * <tt>checkCreateClassLoader</tt>} method is invoked. This may result in
3.329 + * a security exception. </p>
3.330 + *
3.331 + * @throws SecurityException
3.332 + * If a security manager exists and its
3.333 + * <tt>checkCreateClassLoader</tt> method doesn't allow creation
3.334 + * of a new class loader.
3.335 + */
3.336 + protected ClassLoader() {
3.337 + this(checkCreateClassLoader(), getSystemClassLoader());
3.338 + }
3.339 +
3.340 + // -- Class --
3.341 +
3.342 + /**
3.343 + * Loads the class with the specified <a href="#name">binary name</a>.
3.344 + * This method searches for classes in the same manner as the {@link
3.345 + * #loadClass(String, boolean)} method. It is invoked by the Java virtual
3.346 + * machine to resolve class references. Invoking this method is equivalent
3.347 + * to invoking {@link #loadClass(String, boolean) <tt>loadClass(name,
3.348 + * false)</tt>}. </p>
3.349 + *
3.350 + * @param name
3.351 + * The <a href="#name">binary name</a> of the class
3.352 + *
3.353 + * @return The resulting <tt>Class</tt> object
3.354 + *
3.355 + * @throws ClassNotFoundException
3.356 + * If the class was not found
3.357 + */
3.358 + public Class<?> loadClass(String name) throws ClassNotFoundException {
3.359 + return loadClass(name, false);
3.360 + }
3.361 +
3.362 + /**
3.363 + * Loads the class with the specified <a href="#name">binary name</a>. The
3.364 + * default implementation of this method searches for classes in the
3.365 + * following order:
3.366 + *
3.367 + * <p><ol>
3.368 + *
3.369 + * <li><p> Invoke {@link #findLoadedClass(String)} to check if the class
3.370 + * has already been loaded. </p></li>
3.371 + *
3.372 + * <li><p> Invoke the {@link #loadClass(String) <tt>loadClass</tt>} method
3.373 + * on the parent class loader. If the parent is <tt>null</tt> the class
3.374 + * loader built-in to the virtual machine is used, instead. </p></li>
3.375 + *
3.376 + * <li><p> Invoke the {@link #findClass(String)} method to find the
3.377 + * class. </p></li>
3.378 + *
3.379 + * </ol>
3.380 + *
3.381 + * <p> If the class was found using the above steps, and the
3.382 + * <tt>resolve</tt> flag is true, this method will then invoke the {@link
3.383 + * #resolveClass(Class)} method on the resulting <tt>Class</tt> object.
3.384 + *
3.385 + * <p> Subclasses of <tt>ClassLoader</tt> are encouraged to override {@link
3.386 + * #findClass(String)}, rather than this method. </p>
3.387 + *
3.388 + * <p> Unless overridden, this method synchronizes on the result of
3.389 + * {@link #getClassLoadingLock <tt>getClassLoadingLock</tt>} method
3.390 + * during the entire class loading process.
3.391 + *
3.392 + * @param name
3.393 + * The <a href="#name">binary name</a> of the class
3.394 + *
3.395 + * @param resolve
3.396 + * If <tt>true</tt> then resolve the class
3.397 + *
3.398 + * @return The resulting <tt>Class</tt> object
3.399 + *
3.400 + * @throws ClassNotFoundException
3.401 + * If the class could not be found
3.402 + */
3.403 + protected Class<?> loadClass(String name, boolean resolve)
3.404 + throws ClassNotFoundException
3.405 + {
3.406 + synchronized (getClassLoadingLock(name)) {
3.407 + // First, check if the class has already been loaded
3.408 + Class c = findLoadedClass(name);
3.409 + if (c == null) {
3.410 + long t0 = System.nanoTime();
3.411 + try {
3.412 + if (parent != null) {
3.413 + c = parent.loadClass(name, false);
3.414 + } else {
3.415 + c = findBootstrapClassOrNull(name);
3.416 + }
3.417 + } catch (ClassNotFoundException e) {
3.418 + // ClassNotFoundException thrown if class not found
3.419 + // from the non-null parent class loader
3.420 + }
3.421 +
3.422 + if (c == null) {
3.423 + // If still not found, then invoke findClass in order
3.424 + // to find the class.
3.425 + long t1 = System.nanoTime();
3.426 + c = findClass(name);
3.427 +
3.428 + // this is the defining class loader; record the stats
3.429 + sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
3.430 + sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
3.431 + sun.misc.PerfCounter.getFindClasses().increment();
3.432 + }
3.433 + }
3.434 + if (resolve) {
3.435 + resolveClass(c);
3.436 + }
3.437 + return c;
3.438 + }
3.439 + }
3.440 +
3.441 + /**
3.442 + * Returns the lock object for class loading operations.
3.443 + * For backward compatibility, the default implementation of this method
3.444 + * behaves as follows. If this ClassLoader object is registered as
3.445 + * parallel capable, the method returns a dedicated object associated
3.446 + * with the specified class name. Otherwise, the method returns this
3.447 + * ClassLoader object. </p>
3.448 + *
3.449 + * @param className
3.450 + * The name of the to-be-loaded class
3.451 + *
3.452 + * @return the lock for class loading operations
3.453 + *
3.454 + * @throws NullPointerException
3.455 + * If registered as parallel capable and <tt>className</tt> is null
3.456 + *
3.457 + * @see #loadClass(String, boolean)
3.458 + *
3.459 + * @since 1.7
3.460 + */
3.461 + protected Object getClassLoadingLock(String className) {
3.462 + Object lock = this;
3.463 + if (parallelLockMap != null) {
3.464 + Object newLock = new Object();
3.465 + lock = parallelLockMap.putIfAbsent(className, newLock);
3.466 + if (lock == null) {
3.467 + lock = newLock;
3.468 + }
3.469 + }
3.470 + return lock;
3.471 + }
3.472 +
3.473 + // This method is invoked by the virtual machine to load a class.
3.474 + private Class loadClassInternal(String name)
3.475 + throws ClassNotFoundException
3.476 + {
3.477 + // For backward compatibility, explicitly lock on 'this' when
3.478 + // the current class loader is not parallel capable.
3.479 + if (parallelLockMap == null) {
3.480 + synchronized (this) {
3.481 + return loadClass(name);
3.482 + }
3.483 + } else {
3.484 + return loadClass(name);
3.485 + }
3.486 + }
3.487 +
3.488 + // Invoked by the VM after loading class with this loader.
3.489 + private void checkPackageAccess(Class cls, ProtectionDomain pd) {
3.490 + final SecurityManager sm = System.getSecurityManager();
3.491 + if (sm != null) {
3.492 + final String name = cls.getName();
3.493 + final int i = name.lastIndexOf('.');
3.494 + if (i != -1) {
3.495 + AccessController.doPrivileged(new PrivilegedAction<Void>() {
3.496 + public Void run() {
3.497 + sm.checkPackageAccess(name.substring(0, i));
3.498 + return null;
3.499 + }
3.500 + }, new AccessControlContext(new ProtectionDomain[] {pd}));
3.501 + }
3.502 + }
3.503 + domains.add(pd);
3.504 + }
3.505 +
3.506 + /**
3.507 + * Finds the class with the specified <a href="#name">binary name</a>.
3.508 + * This method should be overridden by class loader implementations that
3.509 + * follow the delegation model for loading classes, and will be invoked by
3.510 + * the {@link #loadClass <tt>loadClass</tt>} method after checking the
3.511 + * parent class loader for the requested class. The default implementation
3.512 + * throws a <tt>ClassNotFoundException</tt>. </p>
3.513 + *
3.514 + * @param name
3.515 + * The <a href="#name">binary name</a> of the class
3.516 + *
3.517 + * @return The resulting <tt>Class</tt> object
3.518 + *
3.519 + * @throws ClassNotFoundException
3.520 + * If the class could not be found
3.521 + *
3.522 + * @since 1.2
3.523 + */
3.524 + protected Class<?> findClass(String name) throws ClassNotFoundException {
3.525 + throw new ClassNotFoundException(name);
3.526 + }
3.527 +
3.528 + /**
3.529 + * Converts an array of bytes into an instance of class <tt>Class</tt>.
3.530 + * Before the <tt>Class</tt> can be used it must be resolved. This method
3.531 + * is deprecated in favor of the version that takes a <a
3.532 + * href="#name">binary name</a> as its first argument, and is more secure.
3.533 + *
3.534 + * @param b
3.535 + * The bytes that make up the class data. The bytes in positions
3.536 + * <tt>off</tt> through <tt>off+len-1</tt> should have the format
3.537 + * of a valid class file as defined by
3.538 + * <cite>The Java™ Virtual Machine Specification</cite>.
3.539 + *
3.540 + * @param off
3.541 + * The start offset in <tt>b</tt> of the class data
3.542 + *
3.543 + * @param len
3.544 + * The length of the class data
3.545 + *
3.546 + * @return The <tt>Class</tt> object that was created from the specified
3.547 + * class data
3.548 + *
3.549 + * @throws ClassFormatError
3.550 + * If the data did not contain a valid class
3.551 + *
3.552 + * @throws IndexOutOfBoundsException
3.553 + * If either <tt>off</tt> or <tt>len</tt> is negative, or if
3.554 + * <tt>off+len</tt> is greater than <tt>b.length</tt>.
3.555 + *
3.556 + * @throws SecurityException
3.557 + * If an attempt is made to add this class to a package that
3.558 + * contains classes that were signed by a different set of
3.559 + * certificates than this class, or if an attempt is made
3.560 + * to define a class in a package with a fully-qualified name
3.561 + * that starts with "{@code java.}".
3.562 + *
3.563 + * @see #loadClass(String, boolean)
3.564 + * @see #resolveClass(Class)
3.565 + *
3.566 + * @deprecated Replaced by {@link #defineClass(String, byte[], int, int)
3.567 + * defineClass(String, byte[], int, int)}
3.568 + */
3.569 + @Deprecated
3.570 + protected final Class<?> defineClass(byte[] b, int off, int len)
3.571 + throws ClassFormatError
3.572 + {
3.573 + return defineClass(null, b, off, len, null);
3.574 + }
3.575 +
3.576 + /**
3.577 + * Converts an array of bytes into an instance of class <tt>Class</tt>.
3.578 + * Before the <tt>Class</tt> can be used it must be resolved.
3.579 + *
3.580 + * <p> This method assigns a default {@link java.security.ProtectionDomain
3.581 + * <tt>ProtectionDomain</tt>} to the newly defined class. The
3.582 + * <tt>ProtectionDomain</tt> is effectively granted the same set of
3.583 + * permissions returned when {@link
3.584 + * java.security.Policy#getPermissions(java.security.CodeSource)
3.585 + * <tt>Policy.getPolicy().getPermissions(new CodeSource(null, null))</tt>}
3.586 + * is invoked. The default domain is created on the first invocation of
3.587 + * {@link #defineClass(String, byte[], int, int) <tt>defineClass</tt>},
3.588 + * and re-used on subsequent invocations.
3.589 + *
3.590 + * <p> To assign a specific <tt>ProtectionDomain</tt> to the class, use
3.591 + * the {@link #defineClass(String, byte[], int, int,
3.592 + * java.security.ProtectionDomain) <tt>defineClass</tt>} method that takes a
3.593 + * <tt>ProtectionDomain</tt> as one of its arguments. </p>
3.594 + *
3.595 + * @param name
3.596 + * The expected <a href="#name">binary name</a> of the class, or
3.597 + * <tt>null</tt> if not known
3.598 + *
3.599 + * @param b
3.600 + * The bytes that make up the class data. The bytes in positions
3.601 + * <tt>off</tt> through <tt>off+len-1</tt> should have the format
3.602 + * of a valid class file as defined by
3.603 + * <cite>The Java™ Virtual Machine Specification</cite>.
3.604 + *
3.605 + * @param off
3.606 + * The start offset in <tt>b</tt> of the class data
3.607 + *
3.608 + * @param len
3.609 + * The length of the class data
3.610 + *
3.611 + * @return The <tt>Class</tt> object that was created from the specified
3.612 + * class data.
3.613 + *
3.614 + * @throws ClassFormatError
3.615 + * If the data did not contain a valid class
3.616 + *
3.617 + * @throws IndexOutOfBoundsException
3.618 + * If either <tt>off</tt> or <tt>len</tt> is negative, or if
3.619 + * <tt>off+len</tt> is greater than <tt>b.length</tt>.
3.620 + *
3.621 + * @throws SecurityException
3.622 + * If an attempt is made to add this class to a package that
3.623 + * contains classes that were signed by a different set of
3.624 + * certificates than this class (which is unsigned), or if
3.625 + * <tt>name</tt> begins with "<tt>java.</tt>".
3.626 + *
3.627 + * @see #loadClass(String, boolean)
3.628 + * @see #resolveClass(Class)
3.629 + * @see java.security.CodeSource
3.630 + * @see java.security.SecureClassLoader
3.631 + *
3.632 + * @since 1.1
3.633 + */
3.634 + protected final Class<?> defineClass(String name, byte[] b, int off, int len)
3.635 + throws ClassFormatError
3.636 + {
3.637 + return defineClass(name, b, off, len, null);
3.638 + }
3.639 +
3.640 + /* Determine protection domain, and check that:
3.641 + - not define java.* class,
3.642 + - signer of this class matches signers for the rest of the classes in
3.643 + package.
3.644 + */
3.645 + private ProtectionDomain preDefineClass(String name,
3.646 + ProtectionDomain pd)
3.647 + {
3.648 + if (!checkName(name))
3.649 + throw new NoClassDefFoundError("IllegalName: " + name);
3.650 +
3.651 + if ((name != null) && name.startsWith("java.")) {
3.652 + throw new SecurityException
3.653 + ("Prohibited package name: " +
3.654 + name.substring(0, name.lastIndexOf('.')));
3.655 + }
3.656 + if (pd == null) {
3.657 + pd = defaultDomain;
3.658 + }
3.659 +
3.660 + if (name != null) checkCerts(name, pd.getCodeSource());
3.661 +
3.662 + return pd;
3.663 + }
3.664 +
3.665 + private String defineClassSourceLocation(ProtectionDomain pd)
3.666 + {
3.667 + CodeSource cs = pd.getCodeSource();
3.668 + String source = null;
3.669 + if (cs != null && cs.getLocation() != null) {
3.670 + source = cs.getLocation().toString();
3.671 + }
3.672 + return source;
3.673 + }
3.674 +
3.675 + private Class defineTransformedClass(String name, byte[] b, int off, int len,
3.676 + ProtectionDomain pd,
3.677 + ClassFormatError cfe, String source)
3.678 + throws ClassFormatError
3.679 + {
3.680 + // Class format error - try to transform the bytecode and
3.681 + // define the class again
3.682 + //
3.683 + ClassFileTransformer[] transformers =
3.684 + ClassFileTransformer.getTransformers();
3.685 + Class c = null;
3.686 +
3.687 + if (transformers != null) {
3.688 + for (ClassFileTransformer transformer : transformers) {
3.689 + try {
3.690 + // Transform byte code using transformer
3.691 + byte[] tb = transformer.transform(b, off, len);
3.692 + c = defineClass1(name, tb, 0, tb.length,
3.693 + pd, source);
3.694 + break;
3.695 + } catch (ClassFormatError cfe2) {
3.696 + // If ClassFormatError occurs, try next transformer
3.697 + }
3.698 + }
3.699 + }
3.700 +
3.701 + // Rethrow original ClassFormatError if unable to transform
3.702 + // bytecode to well-formed
3.703 + //
3.704 + if (c == null)
3.705 + throw cfe;
3.706 +
3.707 + return c;
3.708 + }
3.709 +
3.710 + private void postDefineClass(Class c, ProtectionDomain pd)
3.711 + {
3.712 + if (pd.getCodeSource() != null) {
3.713 + Certificate certs[] = pd.getCodeSource().getCertificates();
3.714 + if (certs != null)
3.715 + setSigners(c, certs);
3.716 + }
3.717 + }
3.718 +
3.719 + /**
3.720 + * Converts an array of bytes into an instance of class <tt>Class</tt>,
3.721 + * with an optional <tt>ProtectionDomain</tt>. If the domain is
3.722 + * <tt>null</tt>, then a default domain will be assigned to the class as
3.723 + * specified in the documentation for {@link #defineClass(String, byte[],
3.724 + * int, int)}. Before the class can be used it must be resolved.
3.725 + *
3.726 + * <p> The first class defined in a package determines the exact set of
3.727 + * certificates that all subsequent classes defined in that package must
3.728 + * contain. The set of certificates for a class is obtained from the
3.729 + * {@link java.security.CodeSource <tt>CodeSource</tt>} within the
3.730 + * <tt>ProtectionDomain</tt> of the class. Any classes added to that
3.731 + * package must contain the same set of certificates or a
3.732 + * <tt>SecurityException</tt> will be thrown. Note that if
3.733 + * <tt>name</tt> is <tt>null</tt>, this check is not performed.
3.734 + * You should always pass in the <a href="#name">binary name</a> of the
3.735 + * class you are defining as well as the bytes. This ensures that the
3.736 + * class you are defining is indeed the class you think it is.
3.737 + *
3.738 + * <p> The specified <tt>name</tt> cannot begin with "<tt>java.</tt>", since
3.739 + * all classes in the "<tt>java.*</tt> packages can only be defined by the
3.740 + * bootstrap class loader. If <tt>name</tt> is not <tt>null</tt>, it
3.741 + * must be equal to the <a href="#name">binary name</a> of the class
3.742 + * specified by the byte array "<tt>b</tt>", otherwise a {@link
3.743 + * <tt>NoClassDefFoundError</tt>} will be thrown. </p>
3.744 + *
3.745 + * @param name
3.746 + * The expected <a href="#name">binary name</a> of the class, or
3.747 + * <tt>null</tt> if not known
3.748 + *
3.749 + * @param b
3.750 + * The bytes that make up the class data. The bytes in positions
3.751 + * <tt>off</tt> through <tt>off+len-1</tt> should have the format
3.752 + * of a valid class file as defined by
3.753 + * <cite>The Java™ Virtual Machine Specification</cite>.
3.754 + *
3.755 + * @param off
3.756 + * The start offset in <tt>b</tt> of the class data
3.757 + *
3.758 + * @param len
3.759 + * The length of the class data
3.760 + *
3.761 + * @param protectionDomain
3.762 + * The ProtectionDomain of the class
3.763 + *
3.764 + * @return The <tt>Class</tt> object created from the data,
3.765 + * and optional <tt>ProtectionDomain</tt>.
3.766 + *
3.767 + * @throws ClassFormatError
3.768 + * If the data did not contain a valid class
3.769 + *
3.770 + * @throws NoClassDefFoundError
3.771 + * If <tt>name</tt> is not equal to the <a href="#name">binary
3.772 + * name</a> of the class specified by <tt>b</tt>
3.773 + *
3.774 + * @throws IndexOutOfBoundsException
3.775 + * If either <tt>off</tt> or <tt>len</tt> is negative, or if
3.776 + * <tt>off+len</tt> is greater than <tt>b.length</tt>.
3.777 + *
3.778 + * @throws SecurityException
3.779 + * If an attempt is made to add this class to a package that
3.780 + * contains classes that were signed by a different set of
3.781 + * certificates than this class, or if <tt>name</tt> begins with
3.782 + * "<tt>java.</tt>".
3.783 + */
3.784 + protected final Class<?> defineClass(String name, byte[] b, int off, int len,
3.785 + ProtectionDomain protectionDomain)
3.786 + throws ClassFormatError
3.787 + {
3.788 + protectionDomain = preDefineClass(name, protectionDomain);
3.789 +
3.790 + Class c = null;
3.791 + String source = defineClassSourceLocation(protectionDomain);
3.792 +
3.793 + try {
3.794 + c = defineClass1(name, b, off, len, protectionDomain, source);
3.795 + } catch (ClassFormatError cfe) {
3.796 + c = defineTransformedClass(name, b, off, len, protectionDomain, cfe,
3.797 + source);
3.798 + }
3.799 +
3.800 + postDefineClass(c, protectionDomain);
3.801 + return c;
3.802 + }
3.803 +
3.804 + /**
3.805 + * Converts a {@link java.nio.ByteBuffer <tt>ByteBuffer</tt>}
3.806 + * into an instance of class <tt>Class</tt>,
3.807 + * with an optional <tt>ProtectionDomain</tt>. If the domain is
3.808 + * <tt>null</tt>, then a default domain will be assigned to the class as
3.809 + * specified in the documentation for {@link #defineClass(String, byte[],
3.810 + * int, int)}. Before the class can be used it must be resolved.
3.811 + *
3.812 + * <p>The rules about the first class defined in a package determining the
3.813 + * set of certificates for the package, and the restrictions on class names
3.814 + * are identical to those specified in the documentation for {@link
3.815 + * #defineClass(String, byte[], int, int, ProtectionDomain)}.
3.816 + *
3.817 + * <p> An invocation of this method of the form
3.818 + * <i>cl</i><tt>.defineClass(</tt><i>name</i><tt>,</tt>
3.819 + * <i>bBuffer</i><tt>,</tt> <i>pd</i><tt>)</tt> yields exactly the same
3.820 + * result as the statements
3.821 + *
3.822 + * <blockquote><tt>
3.823 + * ...<br>
3.824 + * byte[] temp = new byte[</tt><i>bBuffer</i><tt>.{@link
3.825 + * java.nio.ByteBuffer#remaining remaining}()];<br>
3.826 + * </tt><i>bBuffer</i><tt>.{@link java.nio.ByteBuffer#get(byte[])
3.827 + * get}(temp);<br>
3.828 + * return {@link #defineClass(String, byte[], int, int, ProtectionDomain)
3.829 + * </tt><i>cl</i><tt>.defineClass}(</tt><i>name</i><tt>, temp, 0,
3.830 + * temp.length, </tt><i>pd</i><tt>);<br>
3.831 + * </tt></blockquote>
3.832 + *
3.833 + * @param name
3.834 + * The expected <a href="#name">binary name</a>. of the class, or
3.835 + * <tt>null</tt> if not known
3.836 + *
3.837 + * @param b
3.838 + * The bytes that make up the class data. The bytes from positions
3.839 + * <tt>b.position()</tt> through <tt>b.position() + b.limit() -1
3.840 + * </tt> should have the format of a valid class file as defined by
3.841 + * <cite>The Java™ Virtual Machine Specification</cite>.
3.842 + *
3.843 + * @param protectionDomain
3.844 + * The ProtectionDomain of the class, or <tt>null</tt>.
3.845 + *
3.846 + * @return The <tt>Class</tt> object created from the data,
3.847 + * and optional <tt>ProtectionDomain</tt>.
3.848 + *
3.849 + * @throws ClassFormatError
3.850 + * If the data did not contain a valid class.
3.851 + *
3.852 + * @throws NoClassDefFoundError
3.853 + * If <tt>name</tt> is not equal to the <a href="#name">binary
3.854 + * name</a> of the class specified by <tt>b</tt>
3.855 + *
3.856 + * @throws SecurityException
3.857 + * If an attempt is made to add this class to a package that
3.858 + * contains classes that were signed by a different set of
3.859 + * certificates than this class, or if <tt>name</tt> begins with
3.860 + * "<tt>java.</tt>".
3.861 + *
3.862 + * @see #defineClass(String, byte[], int, int, ProtectionDomain)
3.863 + *
3.864 + * @since 1.5
3.865 + */
3.866 + protected final Class<?> defineClass(String name, java.nio.ByteBuffer b,
3.867 + ProtectionDomain protectionDomain)
3.868 + throws ClassFormatError
3.869 + {
3.870 + int len = b.remaining();
3.871 +
3.872 + // Use byte[] if not a direct ByteBufer:
3.873 + if (!b.isDirect()) {
3.874 + if (b.hasArray()) {
3.875 + return defineClass(name, b.array(),
3.876 + b.position() + b.arrayOffset(), len,
3.877 + protectionDomain);
3.878 + } else {
3.879 + // no array, or read-only array
3.880 + byte[] tb = new byte[len];
3.881 + b.get(tb); // get bytes out of byte buffer.
3.882 + return defineClass(name, tb, 0, len, protectionDomain);
3.883 + }
3.884 + }
3.885 +
3.886 + protectionDomain = preDefineClass(name, protectionDomain);
3.887 +
3.888 + Class c = null;
3.889 + String source = defineClassSourceLocation(protectionDomain);
3.890 +
3.891 + try {
3.892 + c = defineClass2(name, b, b.position(), len, protectionDomain,
3.893 + source);
3.894 + } catch (ClassFormatError cfe) {
3.895 + byte[] tb = new byte[len];
3.896 + b.get(tb); // get bytes out of byte buffer.
3.897 + c = defineTransformedClass(name, tb, 0, len, protectionDomain, cfe,
3.898 + source);
3.899 + }
3.900 +
3.901 + postDefineClass(c, protectionDomain);
3.902 + return c;
3.903 + }
3.904 +
3.905 + private native Class defineClass0(String name, byte[] b, int off, int len,
3.906 + ProtectionDomain pd);
3.907 +
3.908 + private native Class defineClass1(String name, byte[] b, int off, int len,
3.909 + ProtectionDomain pd, String source);
3.910 +
3.911 + private native Class defineClass2(String name, java.nio.ByteBuffer b,
3.912 + int off, int len, ProtectionDomain pd,
3.913 + String source);
3.914 +
3.915 + // true if the name is null or has the potential to be a valid binary name
3.916 + private boolean checkName(String name) {
3.917 + if ((name == null) || (name.length() == 0))
3.918 + return true;
3.919 + if ((name.indexOf('/') != -1)
3.920 + || (!VM.allowArraySyntax() && (name.charAt(0) == '[')))
3.921 + return false;
3.922 + return true;
3.923 + }
3.924 +
3.925 + private void checkCerts(String name, CodeSource cs) {
3.926 + int i = name.lastIndexOf('.');
3.927 + String pname = (i == -1) ? "" : name.substring(0, i);
3.928 +
3.929 + Certificate[] certs = null;
3.930 + if (cs != null) {
3.931 + certs = cs.getCertificates();
3.932 + }
3.933 + Certificate[] pcerts = null;
3.934 + if (parallelLockMap == null) {
3.935 + synchronized (this) {
3.936 + pcerts = package2certs.get(pname);
3.937 + if (pcerts == null) {
3.938 + package2certs.put(pname, (certs == null? nocerts:certs));
3.939 + }
3.940 + }
3.941 + } else {
3.942 + pcerts = ((ConcurrentHashMap<String, Certificate[]>)package2certs).
3.943 + putIfAbsent(pname, (certs == null? nocerts:certs));
3.944 + }
3.945 + if (pcerts != null && !compareCerts(pcerts, certs)) {
3.946 + throw new SecurityException("class \""+ name +
3.947 + "\"'s signer information does not match signer information of other classes in the same package");
3.948 + }
3.949 + }
3.950 +
3.951 + /**
3.952 + * check to make sure the certs for the new class (certs) are the same as
3.953 + * the certs for the first class inserted in the package (pcerts)
3.954 + */
3.955 + private boolean compareCerts(Certificate[] pcerts,
3.956 + Certificate[] certs)
3.957 + {
3.958 + // certs can be null, indicating no certs.
3.959 + if ((certs == null) || (certs.length == 0)) {
3.960 + return pcerts.length == 0;
3.961 + }
3.962 +
3.963 + // the length must be the same at this point
3.964 + if (certs.length != pcerts.length)
3.965 + return false;
3.966 +
3.967 + // go through and make sure all the certs in one array
3.968 + // are in the other and vice-versa.
3.969 + boolean match;
3.970 + for (int i = 0; i < certs.length; i++) {
3.971 + match = false;
3.972 + for (int j = 0; j < pcerts.length; j++) {
3.973 + if (certs[i].equals(pcerts[j])) {
3.974 + match = true;
3.975 + break;
3.976 + }
3.977 + }
3.978 + if (!match) return false;
3.979 + }
3.980 +
3.981 + // now do the same for pcerts
3.982 + for (int i = 0; i < pcerts.length; i++) {
3.983 + match = false;
3.984 + for (int j = 0; j < certs.length; j++) {
3.985 + if (pcerts[i].equals(certs[j])) {
3.986 + match = true;
3.987 + break;
3.988 + }
3.989 + }
3.990 + if (!match) return false;
3.991 + }
3.992 +
3.993 + return true;
3.994 + }
3.995 +
3.996 + /**
3.997 + * Links the specified class. This (misleadingly named) method may be
3.998 + * used by a class loader to link a class. If the class <tt>c</tt> has
3.999 + * already been linked, then this method simply returns. Otherwise, the
3.1000 + * class is linked as described in the "Execution" chapter of
3.1001 + * <cite>The Java™ Language Specification</cite>.
3.1002 + * </p>
3.1003 + *
3.1004 + * @param c
3.1005 + * The class to link
3.1006 + *
3.1007 + * @throws NullPointerException
3.1008 + * If <tt>c</tt> is <tt>null</tt>.
3.1009 + *
3.1010 + * @see #defineClass(String, byte[], int, int)
3.1011 + */
3.1012 + protected final void resolveClass(Class<?> c) {
3.1013 + resolveClass0(c);
3.1014 + }
3.1015 +
3.1016 + private native void resolveClass0(Class c);
3.1017 +
3.1018 + /**
3.1019 + * Finds a class with the specified <a href="#name">binary name</a>,
3.1020 + * loading it if necessary.
3.1021 + *
3.1022 + * <p> This method loads the class through the system class loader (see
3.1023 + * {@link #getSystemClassLoader()}). The <tt>Class</tt> object returned
3.1024 + * might have more than one <tt>ClassLoader</tt> associated with it.
3.1025 + * Subclasses of <tt>ClassLoader</tt> need not usually invoke this method,
3.1026 + * because most class loaders need to override just {@link
3.1027 + * #findClass(String)}. </p>
3.1028 + *
3.1029 + * @param name
3.1030 + * The <a href="#name">binary name</a> of the class
3.1031 + *
3.1032 + * @return The <tt>Class</tt> object for the specified <tt>name</tt>
3.1033 + *
3.1034 + * @throws ClassNotFoundException
3.1035 + * If the class could not be found
3.1036 + *
3.1037 + * @see #ClassLoader(ClassLoader)
3.1038 + * @see #getParent()
3.1039 + */
3.1040 + protected final Class<?> findSystemClass(String name)
3.1041 + throws ClassNotFoundException
3.1042 + {
3.1043 + ClassLoader system = getSystemClassLoader();
3.1044 + if (system == null) {
3.1045 + if (!checkName(name))
3.1046 + throw new ClassNotFoundException(name);
3.1047 + Class cls = findBootstrapClass(name);
3.1048 + if (cls == null) {
3.1049 + throw new ClassNotFoundException(name);
3.1050 + }
3.1051 + return cls;
3.1052 + }
3.1053 + return system.loadClass(name);
3.1054 + }
3.1055 +
3.1056 + /**
3.1057 + * Returns a class loaded by the bootstrap class loader;
3.1058 + * or return null if not found.
3.1059 + */
3.1060 + private Class findBootstrapClassOrNull(String name)
3.1061 + {
3.1062 + if (!checkName(name)) return null;
3.1063 +
3.1064 + return findBootstrapClass(name);
3.1065 + }
3.1066 +
3.1067 + // return null if not found
3.1068 + private native Class findBootstrapClass(String name);
3.1069 +
3.1070 + /**
3.1071 + * Returns the class with the given <a href="#name">binary name</a> if this
3.1072 + * loader has been recorded by the Java virtual machine as an initiating
3.1073 + * loader of a class with that <a href="#name">binary name</a>. Otherwise
3.1074 + * <tt>null</tt> is returned. </p>
3.1075 + *
3.1076 + * @param name
3.1077 + * The <a href="#name">binary name</a> of the class
3.1078 + *
3.1079 + * @return The <tt>Class</tt> object, or <tt>null</tt> if the class has
3.1080 + * not been loaded
3.1081 + *
3.1082 + * @since 1.1
3.1083 + */
3.1084 + protected final Class<?> findLoadedClass(String name) {
3.1085 + if (!checkName(name))
3.1086 + return null;
3.1087 + return findLoadedClass0(name);
3.1088 + }
3.1089 +
3.1090 + private native final Class findLoadedClass0(String name);
3.1091 +
3.1092 + /**
3.1093 + * Sets the signers of a class. This should be invoked after defining a
3.1094 + * class. </p>
3.1095 + *
3.1096 + * @param c
3.1097 + * The <tt>Class</tt> object
3.1098 + *
3.1099 + * @param signers
3.1100 + * The signers for the class
3.1101 + *
3.1102 + * @since 1.1
3.1103 + */
3.1104 + protected final void setSigners(Class<?> c, Object[] signers) {
3.1105 + c.setSigners(signers);
3.1106 + }
3.1107 +
3.1108 +
3.1109 + // -- Resource --
3.1110 +
3.1111 + /**
3.1112 + * Finds the resource with the given name. A resource is some data
3.1113 + * (images, audio, text, etc) that can be accessed by class code in a way
3.1114 + * that is independent of the location of the code.
3.1115 + *
3.1116 + * <p> The name of a resource is a '<tt>/</tt>'-separated path name that
3.1117 + * identifies the resource.
3.1118 + *
3.1119 + * <p> This method will first search the parent class loader for the
3.1120 + * resource; if the parent is <tt>null</tt> the path of the class loader
3.1121 + * built-in to the virtual machine is searched. That failing, this method
3.1122 + * will invoke {@link #findResource(String)} to find the resource. </p>
3.1123 + *
3.1124 + * @param name
3.1125 + * The resource name
3.1126 + *
3.1127 + * @return A <tt>URL</tt> object for reading the resource, or
3.1128 + * <tt>null</tt> if the resource could not be found or the invoker
3.1129 + * doesn't have adequate privileges to get the resource.
3.1130 + *
3.1131 + * @since 1.1
3.1132 + */
3.1133 + public URL getResource(String name) {
3.1134 + URL url;
3.1135 + if (parent != null) {
3.1136 + url = parent.getResource(name);
3.1137 + } else {
3.1138 + url = getBootstrapResource(name);
3.1139 + }
3.1140 + if (url == null) {
3.1141 + url = findResource(name);
3.1142 + }
3.1143 + return url;
3.1144 + }
3.1145 +
3.1146 + /**
3.1147 + * Finds all the resources with the given name. A resource is some data
3.1148 + * (images, audio, text, etc) that can be accessed by class code in a way
3.1149 + * that is independent of the location of the code.
3.1150 + *
3.1151 + * <p>The name of a resource is a <tt>/</tt>-separated path name that
3.1152 + * identifies the resource.
3.1153 + *
3.1154 + * <p> The search order is described in the documentation for {@link
3.1155 + * #getResource(String)}. </p>
3.1156 + *
3.1157 + * @param name
3.1158 + * The resource name
3.1159 + *
3.1160 + * @return An enumeration of {@link java.net.URL <tt>URL</tt>} objects for
3.1161 + * the resource. If no resources could be found, the enumeration
3.1162 + * will be empty. Resources that the class loader doesn't have
3.1163 + * access to will not be in the enumeration.
3.1164 + *
3.1165 + * @throws IOException
3.1166 + * If I/O errors occur
3.1167 + *
3.1168 + * @see #findResources(String)
3.1169 + *
3.1170 + * @since 1.2
3.1171 + */
3.1172 + public Enumeration<URL> getResources(String name) throws IOException {
3.1173 + Enumeration[] tmp = new Enumeration[2];
3.1174 + if (parent != null) {
3.1175 + tmp[0] = parent.getResources(name);
3.1176 + } else {
3.1177 + tmp[0] = getBootstrapResources(name);
3.1178 + }
3.1179 + tmp[1] = findResources(name);
3.1180 +
3.1181 + return new CompoundEnumeration<>(tmp);
3.1182 + }
3.1183 +
3.1184 + /**
3.1185 + * Finds the resource with the given name. Class loader implementations
3.1186 + * should override this method to specify where to find resources. </p>
3.1187 + *
3.1188 + * @param name
3.1189 + * The resource name
3.1190 + *
3.1191 + * @return A <tt>URL</tt> object for reading the resource, or
3.1192 + * <tt>null</tt> if the resource could not be found
3.1193 + *
3.1194 + * @since 1.2
3.1195 + */
3.1196 + protected URL findResource(String name) {
3.1197 + return null;
3.1198 + }
3.1199 +
3.1200 + /**
3.1201 + * Returns an enumeration of {@link java.net.URL <tt>URL</tt>} objects
3.1202 + * representing all the resources with the given name. Class loader
3.1203 + * implementations should override this method to specify where to load
3.1204 + * resources from. </p>
3.1205 + *
3.1206 + * @param name
3.1207 + * The resource name
3.1208 + *
3.1209 + * @return An enumeration of {@link java.net.URL <tt>URL</tt>} objects for
3.1210 + * the resources
3.1211 + *
3.1212 + * @throws IOException
3.1213 + * If I/O errors occur
3.1214 + *
3.1215 + * @since 1.2
3.1216 + */
3.1217 + protected Enumeration<URL> findResources(String name) throws IOException {
3.1218 + return java.util.Collections.emptyEnumeration();
3.1219 + }
3.1220 +
3.1221 + // index 0: java.lang.ClassLoader.class
3.1222 + // index 1: the immediate caller of index 0.
3.1223 + // index 2: the immediate caller of index 1.
3.1224 + private static native Class<? extends ClassLoader> getCaller(int index);
3.1225 +
3.1226 + /**
3.1227 + * Registers the caller as parallel capable.</p>
3.1228 + * The registration succeeds if and only if all of the following
3.1229 + * conditions are met: <br>
3.1230 + * 1. no instance of the caller has been created</p>
3.1231 + * 2. all of the super classes (except class Object) of the caller are
3.1232 + * registered as parallel capable</p>
3.1233 + * Note that once a class loader is registered as parallel capable, there
3.1234 + * is no way to change it back. </p>
3.1235 + *
3.1236 + * @return true if the caller is successfully registered as
3.1237 + * parallel capable and false if otherwise.
3.1238 + *
3.1239 + * @since 1.7
3.1240 + */
3.1241 + protected static boolean registerAsParallelCapable() {
3.1242 + return ParallelLoaders.register(getCaller(1));
3.1243 + }
3.1244 +
3.1245 + /**
3.1246 + * Find a resource of the specified name from the search path used to load
3.1247 + * classes. This method locates the resource through the system class
3.1248 + * loader (see {@link #getSystemClassLoader()}). </p>
3.1249 + *
3.1250 + * @param name
3.1251 + * The resource name
3.1252 + *
3.1253 + * @return A {@link java.net.URL <tt>URL</tt>} object for reading the
3.1254 + * resource, or <tt>null</tt> if the resource could not be found
3.1255 + *
3.1256 + * @since 1.1
3.1257 + */
3.1258 + public static URL getSystemResource(String name) {
3.1259 + ClassLoader system = getSystemClassLoader();
3.1260 + if (system == null) {
3.1261 + return getBootstrapResource(name);
3.1262 + }
3.1263 + return system.getResource(name);
3.1264 + }
3.1265 +
3.1266 + /**
3.1267 + * Finds all resources of the specified name from the search path used to
3.1268 + * load classes. The resources thus found are returned as an
3.1269 + * {@link java.util.Enumeration <tt>Enumeration</tt>} of {@link
3.1270 + * java.net.URL <tt>URL</tt>} objects.
3.1271 + *
3.1272 + * <p> The search order is described in the documentation for {@link
3.1273 + * #getSystemResource(String)}. </p>
3.1274 + *
3.1275 + * @param name
3.1276 + * The resource name
3.1277 + *
3.1278 + * @return An enumeration of resource {@link java.net.URL <tt>URL</tt>}
3.1279 + * objects
3.1280 + *
3.1281 + * @throws IOException
3.1282 + * If I/O errors occur
3.1283 +
3.1284 + * @since 1.2
3.1285 + */
3.1286 + public static Enumeration<URL> getSystemResources(String name)
3.1287 + throws IOException
3.1288 + {
3.1289 + ClassLoader system = getSystemClassLoader();
3.1290 + if (system == null) {
3.1291 + return getBootstrapResources(name);
3.1292 + }
3.1293 + return system.getResources(name);
3.1294 + }
3.1295 +
3.1296 + /**
3.1297 + * Find resources from the VM's built-in classloader.
3.1298 + */
3.1299 + private static URL getBootstrapResource(String name) {
3.1300 + URLClassPath ucp = getBootstrapClassPath();
3.1301 + Resource res = ucp.getResource(name);
3.1302 + return res != null ? res.getURL() : null;
3.1303 + }
3.1304 +
3.1305 + /**
3.1306 + * Find resources from the VM's built-in classloader.
3.1307 + */
3.1308 + private static Enumeration<URL> getBootstrapResources(String name)
3.1309 + throws IOException
3.1310 + {
3.1311 + final Enumeration<Resource> e =
3.1312 + getBootstrapClassPath().getResources(name);
3.1313 + return new Enumeration<URL> () {
3.1314 + public URL nextElement() {
3.1315 + return e.nextElement().getURL();
3.1316 + }
3.1317 + public boolean hasMoreElements() {
3.1318 + return e.hasMoreElements();
3.1319 + }
3.1320 + };
3.1321 + }
3.1322 +
3.1323 + // Returns the URLClassPath that is used for finding system resources.
3.1324 + static URLClassPath getBootstrapClassPath() {
3.1325 + return sun.misc.Launcher.getBootstrapClassPath();
3.1326 + }
3.1327 +
3.1328 +
3.1329 + /**
3.1330 + * Returns an input stream for reading the specified resource.
3.1331 + *
3.1332 + * <p> The search order is described in the documentation for {@link
3.1333 + * #getResource(String)}. </p>
3.1334 + *
3.1335 + * @param name
3.1336 + * The resource name
3.1337 + *
3.1338 + * @return An input stream for reading the resource, or <tt>null</tt>
3.1339 + * if the resource could not be found
3.1340 + *
3.1341 + * @since 1.1
3.1342 + */
3.1343 + public InputStream getResourceAsStream(String name) {
3.1344 + URL url = getResource(name);
3.1345 + try {
3.1346 + return url != null ? url.openStream() : null;
3.1347 + } catch (IOException e) {
3.1348 + return null;
3.1349 + }
3.1350 + }
3.1351 +
3.1352 + /**
3.1353 + * Open for reading, a resource of the specified name from the search path
3.1354 + * used to load classes. This method locates the resource through the
3.1355 + * system class loader (see {@link #getSystemClassLoader()}). </p>
3.1356 + *
3.1357 + * @param name
3.1358 + * The resource name
3.1359 + *
3.1360 + * @return An input stream for reading the resource, or <tt>null</tt>
3.1361 + * if the resource could not be found
3.1362 + *
3.1363 + * @since 1.1
3.1364 + */
3.1365 + public static InputStream getSystemResourceAsStream(String name) {
3.1366 + URL url = getSystemResource(name);
3.1367 + try {
3.1368 + return url != null ? url.openStream() : null;
3.1369 + } catch (IOException e) {
3.1370 + return null;
3.1371 + }
3.1372 + }
3.1373 +
3.1374 +
3.1375 + // -- Hierarchy --
3.1376 +
3.1377 + /**
3.1378 + * Returns the parent class loader for delegation. Some implementations may
3.1379 + * use <tt>null</tt> to represent the bootstrap class loader. This method
3.1380 + * will return <tt>null</tt> in such implementations if this class loader's
3.1381 + * parent is the bootstrap class loader.
3.1382 + *
3.1383 + * <p> If a security manager is present, and the invoker's class loader is
3.1384 + * not <tt>null</tt> and is not an ancestor of this class loader, then this
3.1385 + * method invokes the security manager's {@link
3.1386 + * SecurityManager#checkPermission(java.security.Permission)
3.1387 + * <tt>checkPermission</tt>} method with a {@link
3.1388 + * RuntimePermission#RuntimePermission(String)
3.1389 + * <tt>RuntimePermission("getClassLoader")</tt>} permission to verify
3.1390 + * access to the parent class loader is permitted. If not, a
3.1391 + * <tt>SecurityException</tt> will be thrown. </p>
3.1392 + *
3.1393 + * @return The parent <tt>ClassLoader</tt>
3.1394 + *
3.1395 + * @throws SecurityException
3.1396 + * If a security manager exists and its <tt>checkPermission</tt>
3.1397 + * method doesn't allow access to this class loader's parent class
3.1398 + * loader.
3.1399 + *
3.1400 + * @since 1.2
3.1401 + */
3.1402 + public final ClassLoader getParent() {
3.1403 + if (parent == null)
3.1404 + return null;
3.1405 + SecurityManager sm = System.getSecurityManager();
3.1406 + if (sm != null) {
3.1407 + ClassLoader ccl = getCallerClassLoader();
3.1408 + if (ccl != null && !isAncestor(ccl)) {
3.1409 + sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
3.1410 + }
3.1411 + }
3.1412 + return parent;
3.1413 + }
3.1414 +
3.1415 + /**
3.1416 + * Returns the system class loader for delegation. This is the default
3.1417 + * delegation parent for new <tt>ClassLoader</tt> instances, and is
3.1418 + * typically the class loader used to start the application.
3.1419 + *
3.1420 + * <p> This method is first invoked early in the runtime's startup
3.1421 + * sequence, at which point it creates the system class loader and sets it
3.1422 + * as the context class loader of the invoking <tt>Thread</tt>.
3.1423 + *
3.1424 + * <p> The default system class loader is an implementation-dependent
3.1425 + * instance of this class.
3.1426 + *
3.1427 + * <p> If the system property "<tt>java.system.class.loader</tt>" is defined
3.1428 + * when this method is first invoked then the value of that property is
3.1429 + * taken to be the name of a class that will be returned as the system
3.1430 + * class loader. The class is loaded using the default system class loader
3.1431 + * and must define a public constructor that takes a single parameter of
3.1432 + * type <tt>ClassLoader</tt> which is used as the delegation parent. An
3.1433 + * instance is then created using this constructor with the default system
3.1434 + * class loader as the parameter. The resulting class loader is defined
3.1435 + * to be the system class loader.
3.1436 + *
3.1437 + * <p> If a security manager is present, and the invoker's class loader is
3.1438 + * not <tt>null</tt> and the invoker's class loader is not the same as or
3.1439 + * an ancestor of the system class loader, then this method invokes the
3.1440 + * security manager's {@link
3.1441 + * SecurityManager#checkPermission(java.security.Permission)
3.1442 + * <tt>checkPermission</tt>} method with a {@link
3.1443 + * RuntimePermission#RuntimePermission(String)
3.1444 + * <tt>RuntimePermission("getClassLoader")</tt>} permission to verify
3.1445 + * access to the system class loader. If not, a
3.1446 + * <tt>SecurityException</tt> will be thrown. </p>
3.1447 + *
3.1448 + * @return The system <tt>ClassLoader</tt> for delegation, or
3.1449 + * <tt>null</tt> if none
3.1450 + *
3.1451 + * @throws SecurityException
3.1452 + * If a security manager exists and its <tt>checkPermission</tt>
3.1453 + * method doesn't allow access to the system class loader.
3.1454 + *
3.1455 + * @throws IllegalStateException
3.1456 + * If invoked recursively during the construction of the class
3.1457 + * loader specified by the "<tt>java.system.class.loader</tt>"
3.1458 + * property.
3.1459 + *
3.1460 + * @throws Error
3.1461 + * If the system property "<tt>java.system.class.loader</tt>"
3.1462 + * is defined but the named class could not be loaded, the
3.1463 + * provider class does not define the required constructor, or an
3.1464 + * exception is thrown by that constructor when it is invoked. The
3.1465 + * underlying cause of the error can be retrieved via the
3.1466 + * {@link Throwable#getCause()} method.
3.1467 + *
3.1468 + * @revised 1.4
3.1469 + */
3.1470 + public static ClassLoader getSystemClassLoader() {
3.1471 + initSystemClassLoader();
3.1472 + if (scl == null) {
3.1473 + return null;
3.1474 + }
3.1475 + SecurityManager sm = System.getSecurityManager();
3.1476 + if (sm != null) {
3.1477 + ClassLoader ccl = getCallerClassLoader();
3.1478 + if (ccl != null && ccl != scl && !scl.isAncestor(ccl)) {
3.1479 + sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
3.1480 + }
3.1481 + }
3.1482 + return scl;
3.1483 + }
3.1484 +
3.1485 + private static synchronized void initSystemClassLoader() {
3.1486 + if (!sclSet) {
3.1487 + if (scl != null)
3.1488 + throw new IllegalStateException("recursive invocation");
3.1489 + sun.misc.Launcher l = sun.misc.Launcher.getLauncher();
3.1490 + if (l != null) {
3.1491 + Throwable oops = null;
3.1492 + scl = l.getClassLoader();
3.1493 + try {
3.1494 + scl = AccessController.doPrivileged(
3.1495 + new SystemClassLoaderAction(scl));
3.1496 + } catch (PrivilegedActionException pae) {
3.1497 + oops = pae.getCause();
3.1498 + if (oops instanceof InvocationTargetException) {
3.1499 + oops = oops.getCause();
3.1500 + }
3.1501 + }
3.1502 + if (oops != null) {
3.1503 + if (oops instanceof Error) {
3.1504 + throw (Error) oops;
3.1505 + } else {
3.1506 + // wrap the exception
3.1507 + throw new Error(oops);
3.1508 + }
3.1509 + }
3.1510 + }
3.1511 + sclSet = true;
3.1512 + }
3.1513 + }
3.1514 +
3.1515 + // Returns true if the specified class loader can be found in this class
3.1516 + // loader's delegation chain.
3.1517 + boolean isAncestor(ClassLoader cl) {
3.1518 + ClassLoader acl = this;
3.1519 + do {
3.1520 + acl = acl.parent;
3.1521 + if (cl == acl) {
3.1522 + return true;
3.1523 + }
3.1524 + } while (acl != null);
3.1525 + return false;
3.1526 + }
3.1527 +
3.1528 + // Returns the invoker's class loader, or null if none.
3.1529 + // NOTE: This must always be invoked when there is exactly one intervening
3.1530 + // frame from the core libraries on the stack between this method's
3.1531 + // invocation and the desired invoker.
3.1532 + static ClassLoader getCallerClassLoader() {
3.1533 + // NOTE use of more generic Reflection.getCallerClass()
3.1534 + Class caller = Reflection.getCallerClass(3);
3.1535 + // This can be null if the VM is requesting it
3.1536 + if (caller == null) {
3.1537 + return null;
3.1538 + }
3.1539 + // Circumvent security check since this is package-private
3.1540 + return caller.getClassLoader0();
3.1541 + }
3.1542 +
3.1543 + // The class loader for the system
3.1544 + // @GuardedBy("ClassLoader.class")
3.1545 + private static ClassLoader scl;
3.1546 +
3.1547 + // Set to true once the system class loader has been set
3.1548 + // @GuardedBy("ClassLoader.class")
3.1549 + private static boolean sclSet;
3.1550 +
3.1551 +
3.1552 + // -- Package --
3.1553 +
3.1554 + /**
3.1555 + * Defines a package by name in this <tt>ClassLoader</tt>. This allows
3.1556 + * class loaders to define the packages for their classes. Packages must
3.1557 + * be created before the class is defined, and package names must be
3.1558 + * unique within a class loader and cannot be redefined or changed once
3.1559 + * created. </p>
3.1560 + *
3.1561 + * @param name
3.1562 + * The package name
3.1563 + *
3.1564 + * @param specTitle
3.1565 + * The specification title
3.1566 + *
3.1567 + * @param specVersion
3.1568 + * The specification version
3.1569 + *
3.1570 + * @param specVendor
3.1571 + * The specification vendor
3.1572 + *
3.1573 + * @param implTitle
3.1574 + * The implementation title
3.1575 + *
3.1576 + * @param implVersion
3.1577 + * The implementation version
3.1578 + *
3.1579 + * @param implVendor
3.1580 + * The implementation vendor
3.1581 + *
3.1582 + * @param sealBase
3.1583 + * If not <tt>null</tt>, then this package is sealed with
3.1584 + * respect to the given code source {@link java.net.URL
3.1585 + * <tt>URL</tt>} object. Otherwise, the package is not sealed.
3.1586 + *
3.1587 + * @return The newly defined <tt>Package</tt> object
3.1588 + *
3.1589 + * @throws IllegalArgumentException
3.1590 + * If package name duplicates an existing package either in this
3.1591 + * class loader or one of its ancestors
3.1592 + *
3.1593 + * @since 1.2
3.1594 + */
3.1595 + protected Package definePackage(String name, String specTitle,
3.1596 + String specVersion, String specVendor,
3.1597 + String implTitle, String implVersion,
3.1598 + String implVendor, URL sealBase)
3.1599 + throws IllegalArgumentException
3.1600 + {
3.1601 + synchronized (packages) {
3.1602 + Package pkg = getPackage(name);
3.1603 + if (pkg != null) {
3.1604 + throw new IllegalArgumentException(name);
3.1605 + }
3.1606 + pkg = new Package(name, specTitle, specVersion, specVendor,
3.1607 + implTitle, implVersion, implVendor,
3.1608 + sealBase, this);
3.1609 + packages.put(name, pkg);
3.1610 + return pkg;
3.1611 + }
3.1612 + }
3.1613 +
3.1614 + /**
3.1615 + * Returns a <tt>Package</tt> that has been defined by this class loader
3.1616 + * or any of its ancestors. </p>
3.1617 + *
3.1618 + * @param name
3.1619 + * The package name
3.1620 + *
3.1621 + * @return The <tt>Package</tt> corresponding to the given name, or
3.1622 + * <tt>null</tt> if not found
3.1623 + *
3.1624 + * @since 1.2
3.1625 + */
3.1626 + protected Package getPackage(String name) {
3.1627 + Package pkg;
3.1628 + synchronized (packages) {
3.1629 + pkg = packages.get(name);
3.1630 + }
3.1631 + if (pkg == null) {
3.1632 + if (parent != null) {
3.1633 + pkg = parent.getPackage(name);
3.1634 + } else {
3.1635 + pkg = Package.getSystemPackage(name);
3.1636 + }
3.1637 + if (pkg != null) {
3.1638 + synchronized (packages) {
3.1639 + Package pkg2 = packages.get(name);
3.1640 + if (pkg2 == null) {
3.1641 + packages.put(name, pkg);
3.1642 + } else {
3.1643 + pkg = pkg2;
3.1644 + }
3.1645 + }
3.1646 + }
3.1647 + }
3.1648 + return pkg;
3.1649 + }
3.1650 +
3.1651 + /**
3.1652 + * Returns all of the <tt>Packages</tt> defined by this class loader and
3.1653 + * its ancestors. </p>
3.1654 + *
3.1655 + * @return The array of <tt>Package</tt> objects defined by this
3.1656 + * <tt>ClassLoader</tt>
3.1657 + *
3.1658 + * @since 1.2
3.1659 + */
3.1660 + protected Package[] getPackages() {
3.1661 + Map<String, Package> map;
3.1662 + synchronized (packages) {
3.1663 + map = new HashMap<>(packages);
3.1664 + }
3.1665 + Package[] pkgs;
3.1666 + if (parent != null) {
3.1667 + pkgs = parent.getPackages();
3.1668 + } else {
3.1669 + pkgs = Package.getSystemPackages();
3.1670 + }
3.1671 + if (pkgs != null) {
3.1672 + for (int i = 0; i < pkgs.length; i++) {
3.1673 + String pkgName = pkgs[i].getName();
3.1674 + if (map.get(pkgName) == null) {
3.1675 + map.put(pkgName, pkgs[i]);
3.1676 + }
3.1677 + }
3.1678 + }
3.1679 + return map.values().toArray(new Package[map.size()]);
3.1680 + }
3.1681 +
3.1682 +
3.1683 + // -- Native library access --
3.1684 +
3.1685 + /**
3.1686 + * Returns the absolute path name of a native library. The VM invokes this
3.1687 + * method to locate the native libraries that belong to classes loaded with
3.1688 + * this class loader. If this method returns <tt>null</tt>, the VM
3.1689 + * searches the library along the path specified as the
3.1690 + * "<tt>java.library.path</tt>" property. </p>
3.1691 + *
3.1692 + * @param libname
3.1693 + * The library name
3.1694 + *
3.1695 + * @return The absolute path of the native library
3.1696 + *
3.1697 + * @see System#loadLibrary(String)
3.1698 + * @see System#mapLibraryName(String)
3.1699 + *
3.1700 + * @since 1.2
3.1701 + */
3.1702 + protected String findLibrary(String libname) {
3.1703 + return null;
3.1704 + }
3.1705 +
3.1706 + /**
3.1707 + * The inner class NativeLibrary denotes a loaded native library instance.
3.1708 + * Every classloader contains a vector of loaded native libraries in the
3.1709 + * private field <tt>nativeLibraries</tt>. The native libraries loaded
3.1710 + * into the system are entered into the <tt>systemNativeLibraries</tt>
3.1711 + * vector.
3.1712 + *
3.1713 + * <p> Every native library requires a particular version of JNI. This is
3.1714 + * denoted by the private <tt>jniVersion</tt> field. This field is set by
3.1715 + * the VM when it loads the library, and used by the VM to pass the correct
3.1716 + * version of JNI to the native methods. </p>
3.1717 + *
3.1718 + * @see ClassLoader
3.1719 + * @since 1.2
3.1720 + */
3.1721 + static class NativeLibrary {
3.1722 + // opaque handle to native library, used in native code.
3.1723 + long handle;
3.1724 + // the version of JNI environment the native library requires.
3.1725 + private int jniVersion;
3.1726 + // the class from which the library is loaded, also indicates
3.1727 + // the loader this native library belongs.
3.1728 + private Class fromClass;
3.1729 + // the canonicalized name of the native library.
3.1730 + String name;
3.1731 +
3.1732 + native void load(String name);
3.1733 + native long find(String name);
3.1734 + native void unload();
3.1735 +
3.1736 + public NativeLibrary(Class fromClass, String name) {
3.1737 + this.name = name;
3.1738 + this.fromClass = fromClass;
3.1739 + }
3.1740 +
3.1741 + protected void finalize() {
3.1742 + synchronized (loadedLibraryNames) {
3.1743 + if (fromClass.getClassLoader() != null && handle != 0) {
3.1744 + /* remove the native library name */
3.1745 + int size = loadedLibraryNames.size();
3.1746 + for (int i = 0; i < size; i++) {
3.1747 + if (name.equals(loadedLibraryNames.elementAt(i))) {
3.1748 + loadedLibraryNames.removeElementAt(i);
3.1749 + break;
3.1750 + }
3.1751 + }
3.1752 + /* unload the library. */
3.1753 + ClassLoader.nativeLibraryContext.push(this);
3.1754 + try {
3.1755 + unload();
3.1756 + } finally {
3.1757 + ClassLoader.nativeLibraryContext.pop();
3.1758 + }
3.1759 + }
3.1760 + }
3.1761 + }
3.1762 + // Invoked in the VM to determine the context class in
3.1763 + // JNI_Load/JNI_Unload
3.1764 + static Class getFromClass() {
3.1765 + return ClassLoader.nativeLibraryContext.peek().fromClass;
3.1766 + }
3.1767 + }
3.1768 +
3.1769 + // All native library names we've loaded.
3.1770 + private static Vector<String> loadedLibraryNames = new Vector<>();
3.1771 +
3.1772 + // Native libraries belonging to system classes.
3.1773 + private static Vector<NativeLibrary> systemNativeLibraries
3.1774 + = new Vector<>();
3.1775 +
3.1776 + // Native libraries associated with the class loader.
3.1777 + private Vector<NativeLibrary> nativeLibraries = new Vector<>();
3.1778 +
3.1779 + // native libraries being loaded/unloaded.
3.1780 + private static Stack<NativeLibrary> nativeLibraryContext = new Stack<>();
3.1781 +
3.1782 + // The paths searched for libraries
3.1783 + private static String usr_paths[];
3.1784 + private static String sys_paths[];
3.1785 +
3.1786 + private static String[] initializePath(String propname) {
3.1787 + String ldpath = System.getProperty(propname, "");
3.1788 + String ps = File.pathSeparator;
3.1789 + int ldlen = ldpath.length();
3.1790 + int i, j, n;
3.1791 + // Count the separators in the path
3.1792 + i = ldpath.indexOf(ps);
3.1793 + n = 0;
3.1794 + while (i >= 0) {
3.1795 + n++;
3.1796 + i = ldpath.indexOf(ps, i + 1);
3.1797 + }
3.1798 +
3.1799 + // allocate the array of paths - n :'s = n + 1 path elements
3.1800 + String[] paths = new String[n + 1];
3.1801 +
3.1802 + // Fill the array with paths from the ldpath
3.1803 + n = i = 0;
3.1804 + j = ldpath.indexOf(ps);
3.1805 + while (j >= 0) {
3.1806 + if (j - i > 0) {
3.1807 + paths[n++] = ldpath.substring(i, j);
3.1808 + } else if (j - i == 0) {
3.1809 + paths[n++] = ".";
3.1810 + }
3.1811 + i = j + 1;
3.1812 + j = ldpath.indexOf(ps, i);
3.1813 + }
3.1814 + paths[n] = ldpath.substring(i, ldlen);
3.1815 + return paths;
3.1816 + }
3.1817 +
3.1818 + // Invoked in the java.lang.Runtime class to implement load and loadLibrary.
3.1819 + static void loadLibrary(Class fromClass, String name,
3.1820 + boolean isAbsolute) {
3.1821 + ClassLoader loader =
3.1822 + (fromClass == null) ? null : fromClass.getClassLoader();
3.1823 + if (sys_paths == null) {
3.1824 + usr_paths = initializePath("java.library.path");
3.1825 + sys_paths = initializePath("sun.boot.library.path");
3.1826 + }
3.1827 + if (isAbsolute) {
3.1828 + if (loadLibrary0(fromClass, new File(name))) {
3.1829 + return;
3.1830 + }
3.1831 + throw new UnsatisfiedLinkError("Can't load library: " + name);
3.1832 + }
3.1833 + if (loader != null) {
3.1834 + String libfilename = loader.findLibrary(name);
3.1835 + if (libfilename != null) {
3.1836 + File libfile = new File(libfilename);
3.1837 + if (!libfile.isAbsolute()) {
3.1838 + throw new UnsatisfiedLinkError(
3.1839 + "ClassLoader.findLibrary failed to return an absolute path: " + libfilename);
3.1840 + }
3.1841 + if (loadLibrary0(fromClass, libfile)) {
3.1842 + return;
3.1843 + }
3.1844 + throw new UnsatisfiedLinkError("Can't load " + libfilename);
3.1845 + }
3.1846 + }
3.1847 + for (int i = 0 ; i < sys_paths.length ; i++) {
3.1848 + File libfile = new File(sys_paths[i], System.mapLibraryName(name));
3.1849 + if (loadLibrary0(fromClass, libfile)) {
3.1850 + return;
3.1851 + }
3.1852 + }
3.1853 + if (loader != null) {
3.1854 + for (int i = 0 ; i < usr_paths.length ; i++) {
3.1855 + File libfile = new File(usr_paths[i],
3.1856 + System.mapLibraryName(name));
3.1857 + if (loadLibrary0(fromClass, libfile)) {
3.1858 + return;
3.1859 + }
3.1860 + }
3.1861 + }
3.1862 + // Oops, it failed
3.1863 + throw new UnsatisfiedLinkError("no " + name + " in java.library.path");
3.1864 + }
3.1865 +
3.1866 + private static boolean loadLibrary0(Class fromClass, final File file) {
3.1867 + boolean exists = AccessController.doPrivileged(
3.1868 + new PrivilegedAction<Object>() {
3.1869 + public Object run() {
3.1870 + return file.exists() ? Boolean.TRUE : null;
3.1871 + }})
3.1872 + != null;
3.1873 + if (!exists) {
3.1874 + return false;
3.1875 + }
3.1876 + String name;
3.1877 + try {
3.1878 + name = file.getCanonicalPath();
3.1879 + } catch (IOException e) {
3.1880 + return false;
3.1881 + }
3.1882 + ClassLoader loader =
3.1883 + (fromClass == null) ? null : fromClass.getClassLoader();
3.1884 + Vector<NativeLibrary> libs =
3.1885 + loader != null ? loader.nativeLibraries : systemNativeLibraries;
3.1886 + synchronized (libs) {
3.1887 + int size = libs.size();
3.1888 + for (int i = 0; i < size; i++) {
3.1889 + NativeLibrary lib = libs.elementAt(i);
3.1890 + if (name.equals(lib.name)) {
3.1891 + return true;
3.1892 + }
3.1893 + }
3.1894 +
3.1895 + synchronized (loadedLibraryNames) {
3.1896 + if (loadedLibraryNames.contains(name)) {
3.1897 + throw new UnsatisfiedLinkError
3.1898 + ("Native Library " +
3.1899 + name +
3.1900 + " already loaded in another classloader");
3.1901 + }
3.1902 + /* If the library is being loaded (must be by the same thread,
3.1903 + * because Runtime.load and Runtime.loadLibrary are
3.1904 + * synchronous). The reason is can occur is that the JNI_OnLoad
3.1905 + * function can cause another loadLibrary invocation.
3.1906 + *
3.1907 + * Thus we can use a static stack to hold the list of libraries
3.1908 + * we are loading.
3.1909 + *
3.1910 + * If there is a pending load operation for the library, we
3.1911 + * immediately return success; otherwise, we raise
3.1912 + * UnsatisfiedLinkError.
3.1913 + */
3.1914 + int n = nativeLibraryContext.size();
3.1915 + for (int i = 0; i < n; i++) {
3.1916 + NativeLibrary lib = nativeLibraryContext.elementAt(i);
3.1917 + if (name.equals(lib.name)) {
3.1918 + if (loader == lib.fromClass.getClassLoader()) {
3.1919 + return true;
3.1920 + } else {
3.1921 + throw new UnsatisfiedLinkError
3.1922 + ("Native Library " +
3.1923 + name +
3.1924 + " is being loaded in another classloader");
3.1925 + }
3.1926 + }
3.1927 + }
3.1928 + NativeLibrary lib = new NativeLibrary(fromClass, name);
3.1929 + nativeLibraryContext.push(lib);
3.1930 + try {
3.1931 + lib.load(name);
3.1932 + } finally {
3.1933 + nativeLibraryContext.pop();
3.1934 + }
3.1935 + if (lib.handle != 0) {
3.1936 + loadedLibraryNames.addElement(name);
3.1937 + libs.addElement(lib);
3.1938 + return true;
3.1939 + }
3.1940 + return false;
3.1941 + }
3.1942 + }
3.1943 + }
3.1944 +
3.1945 + // Invoked in the VM class linking code.
3.1946 + static long findNative(ClassLoader loader, String name) {
3.1947 + Vector<NativeLibrary> libs =
3.1948 + loader != null ? loader.nativeLibraries : systemNativeLibraries;
3.1949 + synchronized (libs) {
3.1950 + int size = libs.size();
3.1951 + for (int i = 0; i < size; i++) {
3.1952 + NativeLibrary lib = libs.elementAt(i);
3.1953 + long entry = lib.find(name);
3.1954 + if (entry != 0)
3.1955 + return entry;
3.1956 + }
3.1957 + }
3.1958 + return 0;
3.1959 + }
3.1960 +
3.1961 +
3.1962 + // -- Assertion management --
3.1963 +
3.1964 + final Object assertionLock;
3.1965 +
3.1966 + // The default toggle for assertion checking.
3.1967 + // @GuardedBy("assertionLock")
3.1968 + private boolean defaultAssertionStatus = false;
3.1969 +
3.1970 + // Maps String packageName to Boolean package default assertion status Note
3.1971 + // that the default package is placed under a null map key. If this field
3.1972 + // is null then we are delegating assertion status queries to the VM, i.e.,
3.1973 + // none of this ClassLoader's assertion status modification methods have
3.1974 + // been invoked.
3.1975 + // @GuardedBy("assertionLock")
3.1976 + private Map<String, Boolean> packageAssertionStatus = null;
3.1977 +
3.1978 + // Maps String fullyQualifiedClassName to Boolean assertionStatus If this
3.1979 + // field is null then we are delegating assertion status queries to the VM,
3.1980 + // i.e., none of this ClassLoader's assertion status modification methods
3.1981 + // have been invoked.
3.1982 + // @GuardedBy("assertionLock")
3.1983 + Map<String, Boolean> classAssertionStatus = null;
3.1984 +
3.1985 + /**
3.1986 + * Sets the default assertion status for this class loader. This setting
3.1987 + * determines whether classes loaded by this class loader and initialized
3.1988 + * in the future will have assertions enabled or disabled by default.
3.1989 + * This setting may be overridden on a per-package or per-class basis by
3.1990 + * invoking {@link #setPackageAssertionStatus(String, boolean)} or {@link
3.1991 + * #setClassAssertionStatus(String, boolean)}. </p>
3.1992 + *
3.1993 + * @param enabled
3.1994 + * <tt>true</tt> if classes loaded by this class loader will
3.1995 + * henceforth have assertions enabled by default, <tt>false</tt>
3.1996 + * if they will have assertions disabled by default.
3.1997 + *
3.1998 + * @since 1.4
3.1999 + */
3.2000 + public void setDefaultAssertionStatus(boolean enabled) {
3.2001 + synchronized (assertionLock) {
3.2002 + if (classAssertionStatus == null)
3.2003 + initializeJavaAssertionMaps();
3.2004 +
3.2005 + defaultAssertionStatus = enabled;
3.2006 + }
3.2007 + }
3.2008 +
3.2009 + /**
3.2010 + * Sets the package default assertion status for the named package. The
3.2011 + * package default assertion status determines the assertion status for
3.2012 + * classes initialized in the future that belong to the named package or
3.2013 + * any of its "subpackages".
3.2014 + *
3.2015 + * <p> A subpackage of a package named p is any package whose name begins
3.2016 + * with "<tt>p.</tt>". For example, <tt>javax.swing.text</tt> is a
3.2017 + * subpackage of <tt>javax.swing</tt>, and both <tt>java.util</tt> and
3.2018 + * <tt>java.lang.reflect</tt> are subpackages of <tt>java</tt>.
3.2019 + *
3.2020 + * <p> In the event that multiple package defaults apply to a given class,
3.2021 + * the package default pertaining to the most specific package takes
3.2022 + * precedence over the others. For example, if <tt>javax.lang</tt> and
3.2023 + * <tt>javax.lang.reflect</tt> both have package defaults associated with
3.2024 + * them, the latter package default applies to classes in
3.2025 + * <tt>javax.lang.reflect</tt>.
3.2026 + *
3.2027 + * <p> Package defaults take precedence over the class loader's default
3.2028 + * assertion status, and may be overridden on a per-class basis by invoking
3.2029 + * {@link #setClassAssertionStatus(String, boolean)}. </p>
3.2030 + *
3.2031 + * @param packageName
3.2032 + * The name of the package whose package default assertion status
3.2033 + * is to be set. A <tt>null</tt> value indicates the unnamed
3.2034 + * package that is "current"
3.2035 + * (see section 7.4.2 of
3.2036 + * <cite>The Java™ Language Specification</cite>.)
3.2037 + *
3.2038 + * @param enabled
3.2039 + * <tt>true</tt> if classes loaded by this classloader and
3.2040 + * belonging to the named package or any of its subpackages will
3.2041 + * have assertions enabled by default, <tt>false</tt> if they will
3.2042 + * have assertions disabled by default.
3.2043 + *
3.2044 + * @since 1.4
3.2045 + */
3.2046 + public void setPackageAssertionStatus(String packageName,
3.2047 + boolean enabled) {
3.2048 + synchronized (assertionLock) {
3.2049 + if (packageAssertionStatus == null)
3.2050 + initializeJavaAssertionMaps();
3.2051 +
3.2052 + packageAssertionStatus.put(packageName, enabled);
3.2053 + }
3.2054 + }
3.2055 +
3.2056 + /**
3.2057 + * Sets the desired assertion status for the named top-level class in this
3.2058 + * class loader and any nested classes contained therein. This setting
3.2059 + * takes precedence over the class loader's default assertion status, and
3.2060 + * over any applicable per-package default. This method has no effect if
3.2061 + * the named class has already been initialized. (Once a class is
3.2062 + * initialized, its assertion status cannot change.)
3.2063 + *
3.2064 + * <p> If the named class is not a top-level class, this invocation will
3.2065 + * have no effect on the actual assertion status of any class. </p>
3.2066 + *
3.2067 + * @param className
3.2068 + * The fully qualified class name of the top-level class whose
3.2069 + * assertion status is to be set.
3.2070 + *
3.2071 + * @param enabled
3.2072 + * <tt>true</tt> if the named class is to have assertions
3.2073 + * enabled when (and if) it is initialized, <tt>false</tt> if the
3.2074 + * class is to have assertions disabled.
3.2075 + *
3.2076 + * @since 1.4
3.2077 + */
3.2078 + public void setClassAssertionStatus(String className, boolean enabled) {
3.2079 + synchronized (assertionLock) {
3.2080 + if (classAssertionStatus == null)
3.2081 + initializeJavaAssertionMaps();
3.2082 +
3.2083 + classAssertionStatus.put(className, enabled);
3.2084 + }
3.2085 + }
3.2086 +
3.2087 + /**
3.2088 + * Sets the default assertion status for this class loader to
3.2089 + * <tt>false</tt> and discards any package defaults or class assertion
3.2090 + * status settings associated with the class loader. This method is
3.2091 + * provided so that class loaders can be made to ignore any command line or
3.2092 + * persistent assertion status settings and "start with a clean slate."
3.2093 + * </p>
3.2094 + *
3.2095 + * @since 1.4
3.2096 + */
3.2097 + public void clearAssertionStatus() {
3.2098 + /*
3.2099 + * Whether or not "Java assertion maps" are initialized, set
3.2100 + * them to empty maps, effectively ignoring any present settings.
3.2101 + */
3.2102 + synchronized (assertionLock) {
3.2103 + classAssertionStatus = new HashMap<>();
3.2104 + packageAssertionStatus = new HashMap<>();
3.2105 + defaultAssertionStatus = false;
3.2106 + }
3.2107 + }
3.2108 +
3.2109 + /**
3.2110 + * Returns the assertion status that would be assigned to the specified
3.2111 + * class if it were to be initialized at the time this method is invoked.
3.2112 + * If the named class has had its assertion status set, the most recent
3.2113 + * setting will be returned; otherwise, if any package default assertion
3.2114 + * status pertains to this class, the most recent setting for the most
3.2115 + * specific pertinent package default assertion status is returned;
3.2116 + * otherwise, this class loader's default assertion status is returned.
3.2117 + * </p>
3.2118 + *
3.2119 + * @param className
3.2120 + * The fully qualified class name of the class whose desired
3.2121 + * assertion status is being queried.
3.2122 + *
3.2123 + * @return The desired assertion status of the specified class.
3.2124 + *
3.2125 + * @see #setClassAssertionStatus(String, boolean)
3.2126 + * @see #setPackageAssertionStatus(String, boolean)
3.2127 + * @see #setDefaultAssertionStatus(boolean)
3.2128 + *
3.2129 + * @since 1.4
3.2130 + */
3.2131 + boolean desiredAssertionStatus(String className) {
3.2132 + synchronized (assertionLock) {
3.2133 + // assert classAssertionStatus != null;
3.2134 + // assert packageAssertionStatus != null;
3.2135 +
3.2136 + // Check for a class entry
3.2137 + Boolean result = classAssertionStatus.get(className);
3.2138 + if (result != null)
3.2139 + return result.booleanValue();
3.2140 +
3.2141 + // Check for most specific package entry
3.2142 + int dotIndex = className.lastIndexOf(".");
3.2143 + if (dotIndex < 0) { // default package
3.2144 + result = packageAssertionStatus.get(null);
3.2145 + if (result != null)
3.2146 + return result.booleanValue();
3.2147 + }
3.2148 + while(dotIndex > 0) {
3.2149 + className = className.substring(0, dotIndex);
3.2150 + result = packageAssertionStatus.get(className);
3.2151 + if (result != null)
3.2152 + return result.booleanValue();
3.2153 + dotIndex = className.lastIndexOf(".", dotIndex-1);
3.2154 + }
3.2155 +
3.2156 + // Return the classloader default
3.2157 + return defaultAssertionStatus;
3.2158 + }
3.2159 + }
3.2160 +
3.2161 + // Set up the assertions with information provided by the VM.
3.2162 + // Note: Should only be called inside a synchronized block
3.2163 + private void initializeJavaAssertionMaps() {
3.2164 + // assert Thread.holdsLock(assertionLock);
3.2165 +
3.2166 + classAssertionStatus = new HashMap<>();
3.2167 + packageAssertionStatus = new HashMap<>();
3.2168 + AssertionStatusDirectives directives = retrieveDirectives();
3.2169 +
3.2170 + for(int i = 0; i < directives.classes.length; i++)
3.2171 + classAssertionStatus.put(directives.classes[i],
3.2172 + directives.classEnabled[i]);
3.2173 +
3.2174 + for(int i = 0; i < directives.packages.length; i++)
3.2175 + packageAssertionStatus.put(directives.packages[i],
3.2176 + directives.packageEnabled[i]);
3.2177 +
3.2178 + defaultAssertionStatus = directives.deflt;
3.2179 + }
3.2180 +
3.2181 + // Retrieves the assertion directives from the VM.
3.2182 + private static native AssertionStatusDirectives retrieveDirectives();
3.2183 +}
3.2184 +
3.2185 +
3.2186 +class SystemClassLoaderAction
3.2187 + implements PrivilegedExceptionAction<ClassLoader> {
3.2188 + private ClassLoader parent;
3.2189 +
3.2190 + SystemClassLoaderAction(ClassLoader parent) {
3.2191 + this.parent = parent;
3.2192 + }
3.2193 +
3.2194 + public ClassLoader run() throws Exception {
3.2195 + String cls = System.getProperty("java.system.class.loader");
3.2196 + if (cls == null) {
3.2197 + return parent;
3.2198 + }
3.2199 +
3.2200 + Constructor ctor = Class.forName(cls, true, parent)
3.2201 + .getDeclaredConstructor(new Class[] { ClassLoader.class });
3.2202 + ClassLoader sys = (ClassLoader) ctor.newInstance(
3.2203 + new Object[] { parent });
3.2204 + Thread.currentThread().setContextClassLoader(sys);
3.2205 + return sys;
3.2206 + }
3.2207 +}