1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/emul/src/main/java/java/lang/ClassLoader.java Tue Oct 30 08:27:04 2012 +0100
1.3 @@ -0,0 +1,2204 @@
1.4 +/*
1.5 + * Copyright (c) 1994, 2011, 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 +package java.lang;
1.29 +
1.30 +import java.io.InputStream;
1.31 +import java.io.IOException;
1.32 +import java.io.File;
1.33 +import java.lang.reflect.Constructor;
1.34 +import java.lang.reflect.InvocationTargetException;
1.35 +import java.net.MalformedURLException;
1.36 +import java.net.URL;
1.37 +import java.security.AccessController;
1.38 +import java.security.AccessControlContext;
1.39 +import java.security.CodeSource;
1.40 +import java.security.Policy;
1.41 +import java.security.PrivilegedAction;
1.42 +import java.security.PrivilegedActionException;
1.43 +import java.security.PrivilegedExceptionAction;
1.44 +import java.security.ProtectionDomain;
1.45 +import java.security.cert.Certificate;
1.46 +import java.util.Collections;
1.47 +import java.util.Enumeration;
1.48 +import java.util.HashMap;
1.49 +import java.util.HashSet;
1.50 +import java.util.Set;
1.51 +import java.util.Stack;
1.52 +import java.util.Map;
1.53 +import java.util.Vector;
1.54 +import java.util.Hashtable;
1.55 +import java.util.WeakHashMap;
1.56 +import java.util.concurrent.ConcurrentHashMap;
1.57 +import sun.misc.ClassFileTransformer;
1.58 +import sun.misc.CompoundEnumeration;
1.59 +import sun.misc.Resource;
1.60 +import sun.misc.URLClassPath;
1.61 +import sun.misc.VM;
1.62 +import sun.reflect.Reflection;
1.63 +import sun.security.util.SecurityConstants;
1.64 +
1.65 +/**
1.66 + * A class loader is an object that is responsible for loading classes. The
1.67 + * class <tt>ClassLoader</tt> is an abstract class. Given the <a
1.68 + * href="#name">binary name</a> of a class, a class loader should attempt to
1.69 + * locate or generate data that constitutes a definition for the class. A
1.70 + * typical strategy is to transform the name into a file name and then read a
1.71 + * "class file" of that name from a file system.
1.72 + *
1.73 + * <p> Every {@link Class <tt>Class</tt>} object contains a {@link
1.74 + * Class#getClassLoader() reference} to the <tt>ClassLoader</tt> that defined
1.75 + * it.
1.76 + *
1.77 + * <p> <tt>Class</tt> objects for array classes are not created by class
1.78 + * loaders, but are created automatically as required by the Java runtime.
1.79 + * The class loader for an array class, as returned by {@link
1.80 + * Class#getClassLoader()} is the same as the class loader for its element
1.81 + * type; if the element type is a primitive type, then the array class has no
1.82 + * class loader.
1.83 + *
1.84 + * <p> Applications implement subclasses of <tt>ClassLoader</tt> in order to
1.85 + * extend the manner in which the Java virtual machine dynamically loads
1.86 + * classes.
1.87 + *
1.88 + * <p> Class loaders may typically be used by security managers to indicate
1.89 + * security domains.
1.90 + *
1.91 + * <p> The <tt>ClassLoader</tt> class uses a delegation model to search for
1.92 + * classes and resources. Each instance of <tt>ClassLoader</tt> has an
1.93 + * associated parent class loader. When requested to find a class or
1.94 + * resource, a <tt>ClassLoader</tt> instance will delegate the search for the
1.95 + * class or resource to its parent class loader before attempting to find the
1.96 + * class or resource itself. The virtual machine's built-in class loader,
1.97 + * called the "bootstrap class loader", does not itself have a parent but may
1.98 + * serve as the parent of a <tt>ClassLoader</tt> instance.
1.99 + *
1.100 + * <p> Class loaders that support concurrent loading of classes are known as
1.101 + * <em>parallel capable</em> class loaders and are required to register
1.102 + * themselves at their class initialization time by invoking the
1.103 + * {@link
1.104 + * #registerAsParallelCapable <tt>ClassLoader.registerAsParallelCapable</tt>}
1.105 + * method. Note that the <tt>ClassLoader</tt> class is registered as parallel
1.106 + * capable by default. However, its subclasses still need to register themselves
1.107 + * if they are parallel capable. <br>
1.108 + * In environments in which the delegation model is not strictly
1.109 + * hierarchical, class loaders need to be parallel capable, otherwise class
1.110 + * loading can lead to deadlocks because the loader lock is held for the
1.111 + * duration of the class loading process (see {@link #loadClass
1.112 + * <tt>loadClass</tt>} methods).
1.113 + *
1.114 + * <p> Normally, the Java virtual machine loads classes from the local file
1.115 + * system in a platform-dependent manner. For example, on UNIX systems, the
1.116 + * virtual machine loads classes from the directory defined by the
1.117 + * <tt>CLASSPATH</tt> environment variable.
1.118 + *
1.119 + * <p> However, some classes may not originate from a file; they may originate
1.120 + * from other sources, such as the network, or they could be constructed by an
1.121 + * application. The method {@link #defineClass(String, byte[], int, int)
1.122 + * <tt>defineClass</tt>} converts an array of bytes into an instance of class
1.123 + * <tt>Class</tt>. Instances of this newly defined class can be created using
1.124 + * {@link Class#newInstance <tt>Class.newInstance</tt>}.
1.125 + *
1.126 + * <p> The methods and constructors of objects created by a class loader may
1.127 + * reference other classes. To determine the class(es) referred to, the Java
1.128 + * virtual machine invokes the {@link #loadClass <tt>loadClass</tt>} method of
1.129 + * the class loader that originally created the class.
1.130 + *
1.131 + * <p> For example, an application could create a network class loader to
1.132 + * download class files from a server. Sample code might look like:
1.133 + *
1.134 + * <blockquote><pre>
1.135 + * ClassLoader loader = new NetworkClassLoader(host, port);
1.136 + * Object main = loader.loadClass("Main", true).newInstance();
1.137 + * . . .
1.138 + * </pre></blockquote>
1.139 + *
1.140 + * <p> The network class loader subclass must define the methods {@link
1.141 + * #findClass <tt>findClass</tt>} and <tt>loadClassData</tt> to load a class
1.142 + * from the network. Once it has downloaded the bytes that make up the class,
1.143 + * it should use the method {@link #defineClass <tt>defineClass</tt>} to
1.144 + * create a class instance. A sample implementation is:
1.145 + *
1.146 + * <blockquote><pre>
1.147 + * class NetworkClassLoader extends ClassLoader {
1.148 + * String host;
1.149 + * int port;
1.150 + *
1.151 + * public Class findClass(String name) {
1.152 + * byte[] b = loadClassData(name);
1.153 + * return defineClass(name, b, 0, b.length);
1.154 + * }
1.155 + *
1.156 + * private byte[] loadClassData(String name) {
1.157 + * // load the class data from the connection
1.158 + * . . .
1.159 + * }
1.160 + * }
1.161 + * </pre></blockquote>
1.162 + *
1.163 + * <h4> <a name="name">Binary names</a> </h4>
1.164 + *
1.165 + * <p> Any class name provided as a {@link String} parameter to methods in
1.166 + * <tt>ClassLoader</tt> must be a binary name as defined by
1.167 + * <cite>The Java™ Language Specification</cite>.
1.168 + *
1.169 + * <p> Examples of valid class names include:
1.170 + * <blockquote><pre>
1.171 + * "java.lang.String"
1.172 + * "javax.swing.JSpinner$DefaultEditor"
1.173 + * "java.security.KeyStore$Builder$FileBuilder$1"
1.174 + * "java.net.URLClassLoader$3$1"
1.175 + * </pre></blockquote>
1.176 + *
1.177 + * @see #resolveClass(Class)
1.178 + * @since 1.0
1.179 + */
1.180 +public abstract class ClassLoader {
1.181 +
1.182 + private static native void registerNatives();
1.183 + static {
1.184 + registerNatives();
1.185 + }
1.186 +
1.187 + // The parent class loader for delegation
1.188 + // Note: VM hardcoded the offset of this field, thus all new fields
1.189 + // must be added *after* it.
1.190 + private final ClassLoader parent;
1.191 +
1.192 + /**
1.193 + * Encapsulates the set of parallel capable loader types.
1.194 + */
1.195 + private static class ParallelLoaders {
1.196 + private ParallelLoaders() {}
1.197 +
1.198 + // the set of parallel capable loader types
1.199 + private static final Set<Class<? extends ClassLoader>> loaderTypes =
1.200 + Collections.newSetFromMap(
1.201 + new WeakHashMap<Class<? extends ClassLoader>, Boolean>());
1.202 + static {
1.203 + synchronized (loaderTypes) { loaderTypes.add(ClassLoader.class); }
1.204 + }
1.205 +
1.206 + /**
1.207 + * Registers the given class loader type as parallel capabale.
1.208 + * Returns {@code true} is successfully registered; {@code false} if
1.209 + * loader's super class is not registered.
1.210 + */
1.211 + static boolean register(Class<? extends ClassLoader> c) {
1.212 + synchronized (loaderTypes) {
1.213 + if (loaderTypes.contains(c.getSuperclass())) {
1.214 + // register the class loader as parallel capable
1.215 + // if and only if all of its super classes are.
1.216 + // Note: given current classloading sequence, if
1.217 + // the immediate super class is parallel capable,
1.218 + // all the super classes higher up must be too.
1.219 + loaderTypes.add(c);
1.220 + return true;
1.221 + } else {
1.222 + return false;
1.223 + }
1.224 + }
1.225 + }
1.226 +
1.227 + /**
1.228 + * Returns {@code true} if the given class loader type is
1.229 + * registered as parallel capable.
1.230 + */
1.231 + static boolean isRegistered(Class<? extends ClassLoader> c) {
1.232 + synchronized (loaderTypes) {
1.233 + return loaderTypes.contains(c);
1.234 + }
1.235 + }
1.236 + }
1.237 +
1.238 + // Maps class name to the corresponding lock object when the current
1.239 + // class loader is parallel capable.
1.240 + // Note: VM also uses this field to decide if the current class loader
1.241 + // is parallel capable and the appropriate lock object for class loading.
1.242 + private final ConcurrentHashMap<String, Object> parallelLockMap;
1.243 +
1.244 + // Hashtable that maps packages to certs
1.245 + private final Map <String, Certificate[]> package2certs;
1.246 +
1.247 + // Shared among all packages with unsigned classes
1.248 + private static final Certificate[] nocerts = new Certificate[0];
1.249 +
1.250 + // The classes loaded by this class loader. The only purpose of this table
1.251 + // is to keep the classes from being GC'ed until the loader is GC'ed.
1.252 + private final Vector<Class<?>> classes = new Vector<>();
1.253 +
1.254 + // The "default" domain. Set as the default ProtectionDomain on newly
1.255 + // created classes.
1.256 + private final ProtectionDomain defaultDomain =
1.257 + new ProtectionDomain(new CodeSource(null, (Certificate[]) null),
1.258 + null, this, null);
1.259 +
1.260 + // The initiating protection domains for all classes loaded by this loader
1.261 + private final Set<ProtectionDomain> domains;
1.262 +
1.263 + // Invoked by the VM to record every loaded class with this loader.
1.264 + void addClass(Class c) {
1.265 + classes.addElement(c);
1.266 + }
1.267 +
1.268 + // The packages defined in this class loader. Each package name is mapped
1.269 + // to its corresponding Package object.
1.270 + // @GuardedBy("itself")
1.271 + private final HashMap<String, Package> packages = new HashMap<>();
1.272 +
1.273 + private static Void checkCreateClassLoader() {
1.274 + SecurityManager security = System.getSecurityManager();
1.275 + if (security != null) {
1.276 + security.checkCreateClassLoader();
1.277 + }
1.278 + return null;
1.279 + }
1.280 +
1.281 + private ClassLoader(Void unused, ClassLoader parent) {
1.282 + this.parent = parent;
1.283 + if (ParallelLoaders.isRegistered(this.getClass())) {
1.284 + parallelLockMap = new ConcurrentHashMap<>();
1.285 + package2certs = new ConcurrentHashMap<>();
1.286 + domains =
1.287 + Collections.synchronizedSet(new HashSet<ProtectionDomain>());
1.288 + assertionLock = new Object();
1.289 + } else {
1.290 + // no finer-grained lock; lock on the classloader instance
1.291 + parallelLockMap = null;
1.292 + package2certs = new Hashtable<>();
1.293 + domains = new HashSet<>();
1.294 + assertionLock = this;
1.295 + }
1.296 + }
1.297 +
1.298 + /**
1.299 + * Creates a new class loader using the specified parent class loader for
1.300 + * delegation.
1.301 + *
1.302 + * <p> If there is a security manager, its {@link
1.303 + * SecurityManager#checkCreateClassLoader()
1.304 + * <tt>checkCreateClassLoader</tt>} method is invoked. This may result in
1.305 + * a security exception. </p>
1.306 + *
1.307 + * @param parent
1.308 + * The parent class loader
1.309 + *
1.310 + * @throws SecurityException
1.311 + * If a security manager exists and its
1.312 + * <tt>checkCreateClassLoader</tt> method doesn't allow creation
1.313 + * of a new class loader.
1.314 + *
1.315 + * @since 1.2
1.316 + */
1.317 + protected ClassLoader(ClassLoader parent) {
1.318 + this(checkCreateClassLoader(), parent);
1.319 + }
1.320 +
1.321 + /**
1.322 + * Creates a new class loader using the <tt>ClassLoader</tt> returned by
1.323 + * the method {@link #getSystemClassLoader()
1.324 + * <tt>getSystemClassLoader()</tt>} as the parent class loader.
1.325 + *
1.326 + * <p> If there is a security manager, its {@link
1.327 + * SecurityManager#checkCreateClassLoader()
1.328 + * <tt>checkCreateClassLoader</tt>} method is invoked. This may result in
1.329 + * a security exception. </p>
1.330 + *
1.331 + * @throws SecurityException
1.332 + * If a security manager exists and its
1.333 + * <tt>checkCreateClassLoader</tt> method doesn't allow creation
1.334 + * of a new class loader.
1.335 + */
1.336 + protected ClassLoader() {
1.337 + this(checkCreateClassLoader(), getSystemClassLoader());
1.338 + }
1.339 +
1.340 + // -- Class --
1.341 +
1.342 + /**
1.343 + * Loads the class with the specified <a href="#name">binary name</a>.
1.344 + * This method searches for classes in the same manner as the {@link
1.345 + * #loadClass(String, boolean)} method. It is invoked by the Java virtual
1.346 + * machine to resolve class references. Invoking this method is equivalent
1.347 + * to invoking {@link #loadClass(String, boolean) <tt>loadClass(name,
1.348 + * false)</tt>}. </p>
1.349 + *
1.350 + * @param name
1.351 + * The <a href="#name">binary name</a> of the class
1.352 + *
1.353 + * @return The resulting <tt>Class</tt> object
1.354 + *
1.355 + * @throws ClassNotFoundException
1.356 + * If the class was not found
1.357 + */
1.358 + public Class<?> loadClass(String name) throws ClassNotFoundException {
1.359 + return loadClass(name, false);
1.360 + }
1.361 +
1.362 + /**
1.363 + * Loads the class with the specified <a href="#name">binary name</a>. The
1.364 + * default implementation of this method searches for classes in the
1.365 + * following order:
1.366 + *
1.367 + * <p><ol>
1.368 + *
1.369 + * <li><p> Invoke {@link #findLoadedClass(String)} to check if the class
1.370 + * has already been loaded. </p></li>
1.371 + *
1.372 + * <li><p> Invoke the {@link #loadClass(String) <tt>loadClass</tt>} method
1.373 + * on the parent class loader. If the parent is <tt>null</tt> the class
1.374 + * loader built-in to the virtual machine is used, instead. </p></li>
1.375 + *
1.376 + * <li><p> Invoke the {@link #findClass(String)} method to find the
1.377 + * class. </p></li>
1.378 + *
1.379 + * </ol>
1.380 + *
1.381 + * <p> If the class was found using the above steps, and the
1.382 + * <tt>resolve</tt> flag is true, this method will then invoke the {@link
1.383 + * #resolveClass(Class)} method on the resulting <tt>Class</tt> object.
1.384 + *
1.385 + * <p> Subclasses of <tt>ClassLoader</tt> are encouraged to override {@link
1.386 + * #findClass(String)}, rather than this method. </p>
1.387 + *
1.388 + * <p> Unless overridden, this method synchronizes on the result of
1.389 + * {@link #getClassLoadingLock <tt>getClassLoadingLock</tt>} method
1.390 + * during the entire class loading process.
1.391 + *
1.392 + * @param name
1.393 + * The <a href="#name">binary name</a> of the class
1.394 + *
1.395 + * @param resolve
1.396 + * If <tt>true</tt> then resolve the class
1.397 + *
1.398 + * @return The resulting <tt>Class</tt> object
1.399 + *
1.400 + * @throws ClassNotFoundException
1.401 + * If the class could not be found
1.402 + */
1.403 + protected Class<?> loadClass(String name, boolean resolve)
1.404 + throws ClassNotFoundException
1.405 + {
1.406 + synchronized (getClassLoadingLock(name)) {
1.407 + // First, check if the class has already been loaded
1.408 + Class c = findLoadedClass(name);
1.409 + if (c == null) {
1.410 + long t0 = System.nanoTime();
1.411 + try {
1.412 + if (parent != null) {
1.413 + c = parent.loadClass(name, false);
1.414 + } else {
1.415 + c = findBootstrapClassOrNull(name);
1.416 + }
1.417 + } catch (ClassNotFoundException e) {
1.418 + // ClassNotFoundException thrown if class not found
1.419 + // from the non-null parent class loader
1.420 + }
1.421 +
1.422 + if (c == null) {
1.423 + // If still not found, then invoke findClass in order
1.424 + // to find the class.
1.425 + long t1 = System.nanoTime();
1.426 + c = findClass(name);
1.427 +
1.428 + // this is the defining class loader; record the stats
1.429 + sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
1.430 + sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
1.431 + sun.misc.PerfCounter.getFindClasses().increment();
1.432 + }
1.433 + }
1.434 + if (resolve) {
1.435 + resolveClass(c);
1.436 + }
1.437 + return c;
1.438 + }
1.439 + }
1.440 +
1.441 + /**
1.442 + * Returns the lock object for class loading operations.
1.443 + * For backward compatibility, the default implementation of this method
1.444 + * behaves as follows. If this ClassLoader object is registered as
1.445 + * parallel capable, the method returns a dedicated object associated
1.446 + * with the specified class name. Otherwise, the method returns this
1.447 + * ClassLoader object. </p>
1.448 + *
1.449 + * @param className
1.450 + * The name of the to-be-loaded class
1.451 + *
1.452 + * @return the lock for class loading operations
1.453 + *
1.454 + * @throws NullPointerException
1.455 + * If registered as parallel capable and <tt>className</tt> is null
1.456 + *
1.457 + * @see #loadClass(String, boolean)
1.458 + *
1.459 + * @since 1.7
1.460 + */
1.461 + protected Object getClassLoadingLock(String className) {
1.462 + Object lock = this;
1.463 + if (parallelLockMap != null) {
1.464 + Object newLock = new Object();
1.465 + lock = parallelLockMap.putIfAbsent(className, newLock);
1.466 + if (lock == null) {
1.467 + lock = newLock;
1.468 + }
1.469 + }
1.470 + return lock;
1.471 + }
1.472 +
1.473 + // This method is invoked by the virtual machine to load a class.
1.474 + private Class loadClassInternal(String name)
1.475 + throws ClassNotFoundException
1.476 + {
1.477 + // For backward compatibility, explicitly lock on 'this' when
1.478 + // the current class loader is not parallel capable.
1.479 + if (parallelLockMap == null) {
1.480 + synchronized (this) {
1.481 + return loadClass(name);
1.482 + }
1.483 + } else {
1.484 + return loadClass(name);
1.485 + }
1.486 + }
1.487 +
1.488 + // Invoked by the VM after loading class with this loader.
1.489 + private void checkPackageAccess(Class cls, ProtectionDomain pd) {
1.490 + final SecurityManager sm = System.getSecurityManager();
1.491 + if (sm != null) {
1.492 + final String name = cls.getName();
1.493 + final int i = name.lastIndexOf('.');
1.494 + if (i != -1) {
1.495 + AccessController.doPrivileged(new PrivilegedAction<Void>() {
1.496 + public Void run() {
1.497 + sm.checkPackageAccess(name.substring(0, i));
1.498 + return null;
1.499 + }
1.500 + }, new AccessControlContext(new ProtectionDomain[] {pd}));
1.501 + }
1.502 + }
1.503 + domains.add(pd);
1.504 + }
1.505 +
1.506 + /**
1.507 + * Finds the class with the specified <a href="#name">binary name</a>.
1.508 + * This method should be overridden by class loader implementations that
1.509 + * follow the delegation model for loading classes, and will be invoked by
1.510 + * the {@link #loadClass <tt>loadClass</tt>} method after checking the
1.511 + * parent class loader for the requested class. The default implementation
1.512 + * throws a <tt>ClassNotFoundException</tt>. </p>
1.513 + *
1.514 + * @param name
1.515 + * The <a href="#name">binary name</a> of the class
1.516 + *
1.517 + * @return The resulting <tt>Class</tt> object
1.518 + *
1.519 + * @throws ClassNotFoundException
1.520 + * If the class could not be found
1.521 + *
1.522 + * @since 1.2
1.523 + */
1.524 + protected Class<?> findClass(String name) throws ClassNotFoundException {
1.525 + throw new ClassNotFoundException(name);
1.526 + }
1.527 +
1.528 + /**
1.529 + * Converts an array of bytes into an instance of class <tt>Class</tt>.
1.530 + * Before the <tt>Class</tt> can be used it must be resolved. This method
1.531 + * is deprecated in favor of the version that takes a <a
1.532 + * href="#name">binary name</a> as its first argument, and is more secure.
1.533 + *
1.534 + * @param b
1.535 + * The bytes that make up the class data. The bytes in positions
1.536 + * <tt>off</tt> through <tt>off+len-1</tt> should have the format
1.537 + * of a valid class file as defined by
1.538 + * <cite>The Java™ Virtual Machine Specification</cite>.
1.539 + *
1.540 + * @param off
1.541 + * The start offset in <tt>b</tt> of the class data
1.542 + *
1.543 + * @param len
1.544 + * The length of the class data
1.545 + *
1.546 + * @return The <tt>Class</tt> object that was created from the specified
1.547 + * class data
1.548 + *
1.549 + * @throws ClassFormatError
1.550 + * If the data did not contain a valid class
1.551 + *
1.552 + * @throws IndexOutOfBoundsException
1.553 + * If either <tt>off</tt> or <tt>len</tt> is negative, or if
1.554 + * <tt>off+len</tt> is greater than <tt>b.length</tt>.
1.555 + *
1.556 + * @throws SecurityException
1.557 + * If an attempt is made to add this class to a package that
1.558 + * contains classes that were signed by a different set of
1.559 + * certificates than this class, or if an attempt is made
1.560 + * to define a class in a package with a fully-qualified name
1.561 + * that starts with "{@code java.}".
1.562 + *
1.563 + * @see #loadClass(String, boolean)
1.564 + * @see #resolveClass(Class)
1.565 + *
1.566 + * @deprecated Replaced by {@link #defineClass(String, byte[], int, int)
1.567 + * defineClass(String, byte[], int, int)}
1.568 + */
1.569 + @Deprecated
1.570 + protected final Class<?> defineClass(byte[] b, int off, int len)
1.571 + throws ClassFormatError
1.572 + {
1.573 + return defineClass(null, b, off, len, null);
1.574 + }
1.575 +
1.576 + /**
1.577 + * Converts an array of bytes into an instance of class <tt>Class</tt>.
1.578 + * Before the <tt>Class</tt> can be used it must be resolved.
1.579 + *
1.580 + * <p> This method assigns a default {@link java.security.ProtectionDomain
1.581 + * <tt>ProtectionDomain</tt>} to the newly defined class. The
1.582 + * <tt>ProtectionDomain</tt> is effectively granted the same set of
1.583 + * permissions returned when {@link
1.584 + * java.security.Policy#getPermissions(java.security.CodeSource)
1.585 + * <tt>Policy.getPolicy().getPermissions(new CodeSource(null, null))</tt>}
1.586 + * is invoked. The default domain is created on the first invocation of
1.587 + * {@link #defineClass(String, byte[], int, int) <tt>defineClass</tt>},
1.588 + * and re-used on subsequent invocations.
1.589 + *
1.590 + * <p> To assign a specific <tt>ProtectionDomain</tt> to the class, use
1.591 + * the {@link #defineClass(String, byte[], int, int,
1.592 + * java.security.ProtectionDomain) <tt>defineClass</tt>} method that takes a
1.593 + * <tt>ProtectionDomain</tt> as one of its arguments. </p>
1.594 + *
1.595 + * @param name
1.596 + * The expected <a href="#name">binary name</a> of the class, or
1.597 + * <tt>null</tt> if not known
1.598 + *
1.599 + * @param b
1.600 + * The bytes that make up the class data. The bytes in positions
1.601 + * <tt>off</tt> through <tt>off+len-1</tt> should have the format
1.602 + * of a valid class file as defined by
1.603 + * <cite>The Java™ Virtual Machine Specification</cite>.
1.604 + *
1.605 + * @param off
1.606 + * The start offset in <tt>b</tt> of the class data
1.607 + *
1.608 + * @param len
1.609 + * The length of the class data
1.610 + *
1.611 + * @return The <tt>Class</tt> object that was created from the specified
1.612 + * class data.
1.613 + *
1.614 + * @throws ClassFormatError
1.615 + * If the data did not contain a valid class
1.616 + *
1.617 + * @throws IndexOutOfBoundsException
1.618 + * If either <tt>off</tt> or <tt>len</tt> is negative, or if
1.619 + * <tt>off+len</tt> is greater than <tt>b.length</tt>.
1.620 + *
1.621 + * @throws SecurityException
1.622 + * If an attempt is made to add this class to a package that
1.623 + * contains classes that were signed by a different set of
1.624 + * certificates than this class (which is unsigned), or if
1.625 + * <tt>name</tt> begins with "<tt>java.</tt>".
1.626 + *
1.627 + * @see #loadClass(String, boolean)
1.628 + * @see #resolveClass(Class)
1.629 + * @see java.security.CodeSource
1.630 + * @see java.security.SecureClassLoader
1.631 + *
1.632 + * @since 1.1
1.633 + */
1.634 + protected final Class<?> defineClass(String name, byte[] b, int off, int len)
1.635 + throws ClassFormatError
1.636 + {
1.637 + return defineClass(name, b, off, len, null);
1.638 + }
1.639 +
1.640 + /* Determine protection domain, and check that:
1.641 + - not define java.* class,
1.642 + - signer of this class matches signers for the rest of the classes in
1.643 + package.
1.644 + */
1.645 + private ProtectionDomain preDefineClass(String name,
1.646 + ProtectionDomain pd)
1.647 + {
1.648 + if (!checkName(name))
1.649 + throw new NoClassDefFoundError("IllegalName: " + name);
1.650 +
1.651 + if ((name != null) && name.startsWith("java.")) {
1.652 + throw new SecurityException
1.653 + ("Prohibited package name: " +
1.654 + name.substring(0, name.lastIndexOf('.')));
1.655 + }
1.656 + if (pd == null) {
1.657 + pd = defaultDomain;
1.658 + }
1.659 +
1.660 + if (name != null) checkCerts(name, pd.getCodeSource());
1.661 +
1.662 + return pd;
1.663 + }
1.664 +
1.665 + private String defineClassSourceLocation(ProtectionDomain pd)
1.666 + {
1.667 + CodeSource cs = pd.getCodeSource();
1.668 + String source = null;
1.669 + if (cs != null && cs.getLocation() != null) {
1.670 + source = cs.getLocation().toString();
1.671 + }
1.672 + return source;
1.673 + }
1.674 +
1.675 + private Class defineTransformedClass(String name, byte[] b, int off, int len,
1.676 + ProtectionDomain pd,
1.677 + ClassFormatError cfe, String source)
1.678 + throws ClassFormatError
1.679 + {
1.680 + // Class format error - try to transform the bytecode and
1.681 + // define the class again
1.682 + //
1.683 + ClassFileTransformer[] transformers =
1.684 + ClassFileTransformer.getTransformers();
1.685 + Class c = null;
1.686 +
1.687 + if (transformers != null) {
1.688 + for (ClassFileTransformer transformer : transformers) {
1.689 + try {
1.690 + // Transform byte code using transformer
1.691 + byte[] tb = transformer.transform(b, off, len);
1.692 + c = defineClass1(name, tb, 0, tb.length,
1.693 + pd, source);
1.694 + break;
1.695 + } catch (ClassFormatError cfe2) {
1.696 + // If ClassFormatError occurs, try next transformer
1.697 + }
1.698 + }
1.699 + }
1.700 +
1.701 + // Rethrow original ClassFormatError if unable to transform
1.702 + // bytecode to well-formed
1.703 + //
1.704 + if (c == null)
1.705 + throw cfe;
1.706 +
1.707 + return c;
1.708 + }
1.709 +
1.710 + private void postDefineClass(Class c, ProtectionDomain pd)
1.711 + {
1.712 + if (pd.getCodeSource() != null) {
1.713 + Certificate certs[] = pd.getCodeSource().getCertificates();
1.714 + if (certs != null)
1.715 + setSigners(c, certs);
1.716 + }
1.717 + }
1.718 +
1.719 + /**
1.720 + * Converts an array of bytes into an instance of class <tt>Class</tt>,
1.721 + * with an optional <tt>ProtectionDomain</tt>. If the domain is
1.722 + * <tt>null</tt>, then a default domain will be assigned to the class as
1.723 + * specified in the documentation for {@link #defineClass(String, byte[],
1.724 + * int, int)}. Before the class can be used it must be resolved.
1.725 + *
1.726 + * <p> The first class defined in a package determines the exact set of
1.727 + * certificates that all subsequent classes defined in that package must
1.728 + * contain. The set of certificates for a class is obtained from the
1.729 + * {@link java.security.CodeSource <tt>CodeSource</tt>} within the
1.730 + * <tt>ProtectionDomain</tt> of the class. Any classes added to that
1.731 + * package must contain the same set of certificates or a
1.732 + * <tt>SecurityException</tt> will be thrown. Note that if
1.733 + * <tt>name</tt> is <tt>null</tt>, this check is not performed.
1.734 + * You should always pass in the <a href="#name">binary name</a> of the
1.735 + * class you are defining as well as the bytes. This ensures that the
1.736 + * class you are defining is indeed the class you think it is.
1.737 + *
1.738 + * <p> The specified <tt>name</tt> cannot begin with "<tt>java.</tt>", since
1.739 + * all classes in the "<tt>java.*</tt> packages can only be defined by the
1.740 + * bootstrap class loader. If <tt>name</tt> is not <tt>null</tt>, it
1.741 + * must be equal to the <a href="#name">binary name</a> of the class
1.742 + * specified by the byte array "<tt>b</tt>", otherwise a {@link
1.743 + * <tt>NoClassDefFoundError</tt>} will be thrown. </p>
1.744 + *
1.745 + * @param name
1.746 + * The expected <a href="#name">binary name</a> of the class, or
1.747 + * <tt>null</tt> if not known
1.748 + *
1.749 + * @param b
1.750 + * The bytes that make up the class data. The bytes in positions
1.751 + * <tt>off</tt> through <tt>off+len-1</tt> should have the format
1.752 + * of a valid class file as defined by
1.753 + * <cite>The Java™ Virtual Machine Specification</cite>.
1.754 + *
1.755 + * @param off
1.756 + * The start offset in <tt>b</tt> of the class data
1.757 + *
1.758 + * @param len
1.759 + * The length of the class data
1.760 + *
1.761 + * @param protectionDomain
1.762 + * The ProtectionDomain of the class
1.763 + *
1.764 + * @return The <tt>Class</tt> object created from the data,
1.765 + * and optional <tt>ProtectionDomain</tt>.
1.766 + *
1.767 + * @throws ClassFormatError
1.768 + * If the data did not contain a valid class
1.769 + *
1.770 + * @throws NoClassDefFoundError
1.771 + * If <tt>name</tt> is not equal to the <a href="#name">binary
1.772 + * name</a> of the class specified by <tt>b</tt>
1.773 + *
1.774 + * @throws IndexOutOfBoundsException
1.775 + * If either <tt>off</tt> or <tt>len</tt> is negative, or if
1.776 + * <tt>off+len</tt> is greater than <tt>b.length</tt>.
1.777 + *
1.778 + * @throws SecurityException
1.779 + * If an attempt is made to add this class to a package that
1.780 + * contains classes that were signed by a different set of
1.781 + * certificates than this class, or if <tt>name</tt> begins with
1.782 + * "<tt>java.</tt>".
1.783 + */
1.784 + protected final Class<?> defineClass(String name, byte[] b, int off, int len,
1.785 + ProtectionDomain protectionDomain)
1.786 + throws ClassFormatError
1.787 + {
1.788 + protectionDomain = preDefineClass(name, protectionDomain);
1.789 +
1.790 + Class c = null;
1.791 + String source = defineClassSourceLocation(protectionDomain);
1.792 +
1.793 + try {
1.794 + c = defineClass1(name, b, off, len, protectionDomain, source);
1.795 + } catch (ClassFormatError cfe) {
1.796 + c = defineTransformedClass(name, b, off, len, protectionDomain, cfe,
1.797 + source);
1.798 + }
1.799 +
1.800 + postDefineClass(c, protectionDomain);
1.801 + return c;
1.802 + }
1.803 +
1.804 + /**
1.805 + * Converts a {@link java.nio.ByteBuffer <tt>ByteBuffer</tt>}
1.806 + * into an instance of class <tt>Class</tt>,
1.807 + * with an optional <tt>ProtectionDomain</tt>. If the domain is
1.808 + * <tt>null</tt>, then a default domain will be assigned to the class as
1.809 + * specified in the documentation for {@link #defineClass(String, byte[],
1.810 + * int, int)}. Before the class can be used it must be resolved.
1.811 + *
1.812 + * <p>The rules about the first class defined in a package determining the
1.813 + * set of certificates for the package, and the restrictions on class names
1.814 + * are identical to those specified in the documentation for {@link
1.815 + * #defineClass(String, byte[], int, int, ProtectionDomain)}.
1.816 + *
1.817 + * <p> An invocation of this method of the form
1.818 + * <i>cl</i><tt>.defineClass(</tt><i>name</i><tt>,</tt>
1.819 + * <i>bBuffer</i><tt>,</tt> <i>pd</i><tt>)</tt> yields exactly the same
1.820 + * result as the statements
1.821 + *
1.822 + * <blockquote><tt>
1.823 + * ...<br>
1.824 + * byte[] temp = new byte[</tt><i>bBuffer</i><tt>.{@link
1.825 + * java.nio.ByteBuffer#remaining remaining}()];<br>
1.826 + * </tt><i>bBuffer</i><tt>.{@link java.nio.ByteBuffer#get(byte[])
1.827 + * get}(temp);<br>
1.828 + * return {@link #defineClass(String, byte[], int, int, ProtectionDomain)
1.829 + * </tt><i>cl</i><tt>.defineClass}(</tt><i>name</i><tt>, temp, 0,
1.830 + * temp.length, </tt><i>pd</i><tt>);<br>
1.831 + * </tt></blockquote>
1.832 + *
1.833 + * @param name
1.834 + * The expected <a href="#name">binary name</a>. of the class, or
1.835 + * <tt>null</tt> if not known
1.836 + *
1.837 + * @param b
1.838 + * The bytes that make up the class data. The bytes from positions
1.839 + * <tt>b.position()</tt> through <tt>b.position() + b.limit() -1
1.840 + * </tt> should have the format of a valid class file as defined by
1.841 + * <cite>The Java™ Virtual Machine Specification</cite>.
1.842 + *
1.843 + * @param protectionDomain
1.844 + * The ProtectionDomain of the class, or <tt>null</tt>.
1.845 + *
1.846 + * @return The <tt>Class</tt> object created from the data,
1.847 + * and optional <tt>ProtectionDomain</tt>.
1.848 + *
1.849 + * @throws ClassFormatError
1.850 + * If the data did not contain a valid class.
1.851 + *
1.852 + * @throws NoClassDefFoundError
1.853 + * If <tt>name</tt> is not equal to the <a href="#name">binary
1.854 + * name</a> of the class specified by <tt>b</tt>
1.855 + *
1.856 + * @throws SecurityException
1.857 + * If an attempt is made to add this class to a package that
1.858 + * contains classes that were signed by a different set of
1.859 + * certificates than this class, or if <tt>name</tt> begins with
1.860 + * "<tt>java.</tt>".
1.861 + *
1.862 + * @see #defineClass(String, byte[], int, int, ProtectionDomain)
1.863 + *
1.864 + * @since 1.5
1.865 + */
1.866 + protected final Class<?> defineClass(String name, java.nio.ByteBuffer b,
1.867 + ProtectionDomain protectionDomain)
1.868 + throws ClassFormatError
1.869 + {
1.870 + int len = b.remaining();
1.871 +
1.872 + // Use byte[] if not a direct ByteBufer:
1.873 + if (!b.isDirect()) {
1.874 + if (b.hasArray()) {
1.875 + return defineClass(name, b.array(),
1.876 + b.position() + b.arrayOffset(), len,
1.877 + protectionDomain);
1.878 + } else {
1.879 + // no array, or read-only array
1.880 + byte[] tb = new byte[len];
1.881 + b.get(tb); // get bytes out of byte buffer.
1.882 + return defineClass(name, tb, 0, len, protectionDomain);
1.883 + }
1.884 + }
1.885 +
1.886 + protectionDomain = preDefineClass(name, protectionDomain);
1.887 +
1.888 + Class c = null;
1.889 + String source = defineClassSourceLocation(protectionDomain);
1.890 +
1.891 + try {
1.892 + c = defineClass2(name, b, b.position(), len, protectionDomain,
1.893 + source);
1.894 + } catch (ClassFormatError cfe) {
1.895 + byte[] tb = new byte[len];
1.896 + b.get(tb); // get bytes out of byte buffer.
1.897 + c = defineTransformedClass(name, tb, 0, len, protectionDomain, cfe,
1.898 + source);
1.899 + }
1.900 +
1.901 + postDefineClass(c, protectionDomain);
1.902 + return c;
1.903 + }
1.904 +
1.905 + private native Class defineClass0(String name, byte[] b, int off, int len,
1.906 + ProtectionDomain pd);
1.907 +
1.908 + private native Class defineClass1(String name, byte[] b, int off, int len,
1.909 + ProtectionDomain pd, String source);
1.910 +
1.911 + private native Class defineClass2(String name, java.nio.ByteBuffer b,
1.912 + int off, int len, ProtectionDomain pd,
1.913 + String source);
1.914 +
1.915 + // true if the name is null or has the potential to be a valid binary name
1.916 + private boolean checkName(String name) {
1.917 + if ((name == null) || (name.length() == 0))
1.918 + return true;
1.919 + if ((name.indexOf('/') != -1)
1.920 + || (!VM.allowArraySyntax() && (name.charAt(0) == '[')))
1.921 + return false;
1.922 + return true;
1.923 + }
1.924 +
1.925 + private void checkCerts(String name, CodeSource cs) {
1.926 + int i = name.lastIndexOf('.');
1.927 + String pname = (i == -1) ? "" : name.substring(0, i);
1.928 +
1.929 + Certificate[] certs = null;
1.930 + if (cs != null) {
1.931 + certs = cs.getCertificates();
1.932 + }
1.933 + Certificate[] pcerts = null;
1.934 + if (parallelLockMap == null) {
1.935 + synchronized (this) {
1.936 + pcerts = package2certs.get(pname);
1.937 + if (pcerts == null) {
1.938 + package2certs.put(pname, (certs == null? nocerts:certs));
1.939 + }
1.940 + }
1.941 + } else {
1.942 + pcerts = ((ConcurrentHashMap<String, Certificate[]>)package2certs).
1.943 + putIfAbsent(pname, (certs == null? nocerts:certs));
1.944 + }
1.945 + if (pcerts != null && !compareCerts(pcerts, certs)) {
1.946 + throw new SecurityException("class \""+ name +
1.947 + "\"'s signer information does not match signer information of other classes in the same package");
1.948 + }
1.949 + }
1.950 +
1.951 + /**
1.952 + * check to make sure the certs for the new class (certs) are the same as
1.953 + * the certs for the first class inserted in the package (pcerts)
1.954 + */
1.955 + private boolean compareCerts(Certificate[] pcerts,
1.956 + Certificate[] certs)
1.957 + {
1.958 + // certs can be null, indicating no certs.
1.959 + if ((certs == null) || (certs.length == 0)) {
1.960 + return pcerts.length == 0;
1.961 + }
1.962 +
1.963 + // the length must be the same at this point
1.964 + if (certs.length != pcerts.length)
1.965 + return false;
1.966 +
1.967 + // go through and make sure all the certs in one array
1.968 + // are in the other and vice-versa.
1.969 + boolean match;
1.970 + for (int i = 0; i < certs.length; i++) {
1.971 + match = false;
1.972 + for (int j = 0; j < pcerts.length; j++) {
1.973 + if (certs[i].equals(pcerts[j])) {
1.974 + match = true;
1.975 + break;
1.976 + }
1.977 + }
1.978 + if (!match) return false;
1.979 + }
1.980 +
1.981 + // now do the same for pcerts
1.982 + for (int i = 0; i < pcerts.length; i++) {
1.983 + match = false;
1.984 + for (int j = 0; j < certs.length; j++) {
1.985 + if (pcerts[i].equals(certs[j])) {
1.986 + match = true;
1.987 + break;
1.988 + }
1.989 + }
1.990 + if (!match) return false;
1.991 + }
1.992 +
1.993 + return true;
1.994 + }
1.995 +
1.996 + /**
1.997 + * Links the specified class. This (misleadingly named) method may be
1.998 + * used by a class loader to link a class. If the class <tt>c</tt> has
1.999 + * already been linked, then this method simply returns. Otherwise, the
1.1000 + * class is linked as described in the "Execution" chapter of
1.1001 + * <cite>The Java™ Language Specification</cite>.
1.1002 + * </p>
1.1003 + *
1.1004 + * @param c
1.1005 + * The class to link
1.1006 + *
1.1007 + * @throws NullPointerException
1.1008 + * If <tt>c</tt> is <tt>null</tt>.
1.1009 + *
1.1010 + * @see #defineClass(String, byte[], int, int)
1.1011 + */
1.1012 + protected final void resolveClass(Class<?> c) {
1.1013 + resolveClass0(c);
1.1014 + }
1.1015 +
1.1016 + private native void resolveClass0(Class c);
1.1017 +
1.1018 + /**
1.1019 + * Finds a class with the specified <a href="#name">binary name</a>,
1.1020 + * loading it if necessary.
1.1021 + *
1.1022 + * <p> This method loads the class through the system class loader (see
1.1023 + * {@link #getSystemClassLoader()}). The <tt>Class</tt> object returned
1.1024 + * might have more than one <tt>ClassLoader</tt> associated with it.
1.1025 + * Subclasses of <tt>ClassLoader</tt> need not usually invoke this method,
1.1026 + * because most class loaders need to override just {@link
1.1027 + * #findClass(String)}. </p>
1.1028 + *
1.1029 + * @param name
1.1030 + * The <a href="#name">binary name</a> of the class
1.1031 + *
1.1032 + * @return The <tt>Class</tt> object for the specified <tt>name</tt>
1.1033 + *
1.1034 + * @throws ClassNotFoundException
1.1035 + * If the class could not be found
1.1036 + *
1.1037 + * @see #ClassLoader(ClassLoader)
1.1038 + * @see #getParent()
1.1039 + */
1.1040 + protected final Class<?> findSystemClass(String name)
1.1041 + throws ClassNotFoundException
1.1042 + {
1.1043 + ClassLoader system = getSystemClassLoader();
1.1044 + if (system == null) {
1.1045 + if (!checkName(name))
1.1046 + throw new ClassNotFoundException(name);
1.1047 + Class cls = findBootstrapClass(name);
1.1048 + if (cls == null) {
1.1049 + throw new ClassNotFoundException(name);
1.1050 + }
1.1051 + return cls;
1.1052 + }
1.1053 + return system.loadClass(name);
1.1054 + }
1.1055 +
1.1056 + /**
1.1057 + * Returns a class loaded by the bootstrap class loader;
1.1058 + * or return null if not found.
1.1059 + */
1.1060 + private Class findBootstrapClassOrNull(String name)
1.1061 + {
1.1062 + if (!checkName(name)) return null;
1.1063 +
1.1064 + return findBootstrapClass(name);
1.1065 + }
1.1066 +
1.1067 + // return null if not found
1.1068 + private native Class findBootstrapClass(String name);
1.1069 +
1.1070 + /**
1.1071 + * Returns the class with the given <a href="#name">binary name</a> if this
1.1072 + * loader has been recorded by the Java virtual machine as an initiating
1.1073 + * loader of a class with that <a href="#name">binary name</a>. Otherwise
1.1074 + * <tt>null</tt> is returned. </p>
1.1075 + *
1.1076 + * @param name
1.1077 + * The <a href="#name">binary name</a> of the class
1.1078 + *
1.1079 + * @return The <tt>Class</tt> object, or <tt>null</tt> if the class has
1.1080 + * not been loaded
1.1081 + *
1.1082 + * @since 1.1
1.1083 + */
1.1084 + protected final Class<?> findLoadedClass(String name) {
1.1085 + if (!checkName(name))
1.1086 + return null;
1.1087 + return findLoadedClass0(name);
1.1088 + }
1.1089 +
1.1090 + private native final Class findLoadedClass0(String name);
1.1091 +
1.1092 + /**
1.1093 + * Sets the signers of a class. This should be invoked after defining a
1.1094 + * class. </p>
1.1095 + *
1.1096 + * @param c
1.1097 + * The <tt>Class</tt> object
1.1098 + *
1.1099 + * @param signers
1.1100 + * The signers for the class
1.1101 + *
1.1102 + * @since 1.1
1.1103 + */
1.1104 + protected final void setSigners(Class<?> c, Object[] signers) {
1.1105 + c.setSigners(signers);
1.1106 + }
1.1107 +
1.1108 +
1.1109 + // -- Resource --
1.1110 +
1.1111 + /**
1.1112 + * Finds the resource with the given name. A resource is some data
1.1113 + * (images, audio, text, etc) that can be accessed by class code in a way
1.1114 + * that is independent of the location of the code.
1.1115 + *
1.1116 + * <p> The name of a resource is a '<tt>/</tt>'-separated path name that
1.1117 + * identifies the resource.
1.1118 + *
1.1119 + * <p> This method will first search the parent class loader for the
1.1120 + * resource; if the parent is <tt>null</tt> the path of the class loader
1.1121 + * built-in to the virtual machine is searched. That failing, this method
1.1122 + * will invoke {@link #findResource(String)} to find the resource. </p>
1.1123 + *
1.1124 + * @param name
1.1125 + * The resource name
1.1126 + *
1.1127 + * @return A <tt>URL</tt> object for reading the resource, or
1.1128 + * <tt>null</tt> if the resource could not be found or the invoker
1.1129 + * doesn't have adequate privileges to get the resource.
1.1130 + *
1.1131 + * @since 1.1
1.1132 + */
1.1133 + public URL getResource(String name) {
1.1134 + URL url;
1.1135 + if (parent != null) {
1.1136 + url = parent.getResource(name);
1.1137 + } else {
1.1138 + url = getBootstrapResource(name);
1.1139 + }
1.1140 + if (url == null) {
1.1141 + url = findResource(name);
1.1142 + }
1.1143 + return url;
1.1144 + }
1.1145 +
1.1146 + /**
1.1147 + * Finds all the resources with the given name. A resource is some data
1.1148 + * (images, audio, text, etc) that can be accessed by class code in a way
1.1149 + * that is independent of the location of the code.
1.1150 + *
1.1151 + * <p>The name of a resource is a <tt>/</tt>-separated path name that
1.1152 + * identifies the resource.
1.1153 + *
1.1154 + * <p> The search order is described in the documentation for {@link
1.1155 + * #getResource(String)}. </p>
1.1156 + *
1.1157 + * @param name
1.1158 + * The resource name
1.1159 + *
1.1160 + * @return An enumeration of {@link java.net.URL <tt>URL</tt>} objects for
1.1161 + * the resource. If no resources could be found, the enumeration
1.1162 + * will be empty. Resources that the class loader doesn't have
1.1163 + * access to will not be in the enumeration.
1.1164 + *
1.1165 + * @throws IOException
1.1166 + * If I/O errors occur
1.1167 + *
1.1168 + * @see #findResources(String)
1.1169 + *
1.1170 + * @since 1.2
1.1171 + */
1.1172 + public Enumeration<URL> getResources(String name) throws IOException {
1.1173 + Enumeration[] tmp = new Enumeration[2];
1.1174 + if (parent != null) {
1.1175 + tmp[0] = parent.getResources(name);
1.1176 + } else {
1.1177 + tmp[0] = getBootstrapResources(name);
1.1178 + }
1.1179 + tmp[1] = findResources(name);
1.1180 +
1.1181 + return new CompoundEnumeration<>(tmp);
1.1182 + }
1.1183 +
1.1184 + /**
1.1185 + * Finds the resource with the given name. Class loader implementations
1.1186 + * should override this method to specify where to find resources. </p>
1.1187 + *
1.1188 + * @param name
1.1189 + * The resource name
1.1190 + *
1.1191 + * @return A <tt>URL</tt> object for reading the resource, or
1.1192 + * <tt>null</tt> if the resource could not be found
1.1193 + *
1.1194 + * @since 1.2
1.1195 + */
1.1196 + protected URL findResource(String name) {
1.1197 + return null;
1.1198 + }
1.1199 +
1.1200 + /**
1.1201 + * Returns an enumeration of {@link java.net.URL <tt>URL</tt>} objects
1.1202 + * representing all the resources with the given name. Class loader
1.1203 + * implementations should override this method to specify where to load
1.1204 + * resources from. </p>
1.1205 + *
1.1206 + * @param name
1.1207 + * The resource name
1.1208 + *
1.1209 + * @return An enumeration of {@link java.net.URL <tt>URL</tt>} objects for
1.1210 + * the resources
1.1211 + *
1.1212 + * @throws IOException
1.1213 + * If I/O errors occur
1.1214 + *
1.1215 + * @since 1.2
1.1216 + */
1.1217 + protected Enumeration<URL> findResources(String name) throws IOException {
1.1218 + return java.util.Collections.emptyEnumeration();
1.1219 + }
1.1220 +
1.1221 + // index 0: java.lang.ClassLoader.class
1.1222 + // index 1: the immediate caller of index 0.
1.1223 + // index 2: the immediate caller of index 1.
1.1224 + private static native Class<? extends ClassLoader> getCaller(int index);
1.1225 +
1.1226 + /**
1.1227 + * Registers the caller as parallel capable.</p>
1.1228 + * The registration succeeds if and only if all of the following
1.1229 + * conditions are met: <br>
1.1230 + * 1. no instance of the caller has been created</p>
1.1231 + * 2. all of the super classes (except class Object) of the caller are
1.1232 + * registered as parallel capable</p>
1.1233 + * Note that once a class loader is registered as parallel capable, there
1.1234 + * is no way to change it back. </p>
1.1235 + *
1.1236 + * @return true if the caller is successfully registered as
1.1237 + * parallel capable and false if otherwise.
1.1238 + *
1.1239 + * @since 1.7
1.1240 + */
1.1241 + protected static boolean registerAsParallelCapable() {
1.1242 + return ParallelLoaders.register(getCaller(1));
1.1243 + }
1.1244 +
1.1245 + /**
1.1246 + * Find a resource of the specified name from the search path used to load
1.1247 + * classes. This method locates the resource through the system class
1.1248 + * loader (see {@link #getSystemClassLoader()}). </p>
1.1249 + *
1.1250 + * @param name
1.1251 + * The resource name
1.1252 + *
1.1253 + * @return A {@link java.net.URL <tt>URL</tt>} object for reading the
1.1254 + * resource, or <tt>null</tt> if the resource could not be found
1.1255 + *
1.1256 + * @since 1.1
1.1257 + */
1.1258 + public static URL getSystemResource(String name) {
1.1259 + ClassLoader system = getSystemClassLoader();
1.1260 + if (system == null) {
1.1261 + return getBootstrapResource(name);
1.1262 + }
1.1263 + return system.getResource(name);
1.1264 + }
1.1265 +
1.1266 + /**
1.1267 + * Finds all resources of the specified name from the search path used to
1.1268 + * load classes. The resources thus found are returned as an
1.1269 + * {@link java.util.Enumeration <tt>Enumeration</tt>} of {@link
1.1270 + * java.net.URL <tt>URL</tt>} objects.
1.1271 + *
1.1272 + * <p> The search order is described in the documentation for {@link
1.1273 + * #getSystemResource(String)}. </p>
1.1274 + *
1.1275 + * @param name
1.1276 + * The resource name
1.1277 + *
1.1278 + * @return An enumeration of resource {@link java.net.URL <tt>URL</tt>}
1.1279 + * objects
1.1280 + *
1.1281 + * @throws IOException
1.1282 + * If I/O errors occur
1.1283 +
1.1284 + * @since 1.2
1.1285 + */
1.1286 + public static Enumeration<URL> getSystemResources(String name)
1.1287 + throws IOException
1.1288 + {
1.1289 + ClassLoader system = getSystemClassLoader();
1.1290 + if (system == null) {
1.1291 + return getBootstrapResources(name);
1.1292 + }
1.1293 + return system.getResources(name);
1.1294 + }
1.1295 +
1.1296 + /**
1.1297 + * Find resources from the VM's built-in classloader.
1.1298 + */
1.1299 + private static URL getBootstrapResource(String name) {
1.1300 + URLClassPath ucp = getBootstrapClassPath();
1.1301 + Resource res = ucp.getResource(name);
1.1302 + return res != null ? res.getURL() : null;
1.1303 + }
1.1304 +
1.1305 + /**
1.1306 + * Find resources from the VM's built-in classloader.
1.1307 + */
1.1308 + private static Enumeration<URL> getBootstrapResources(String name)
1.1309 + throws IOException
1.1310 + {
1.1311 + final Enumeration<Resource> e =
1.1312 + getBootstrapClassPath().getResources(name);
1.1313 + return new Enumeration<URL> () {
1.1314 + public URL nextElement() {
1.1315 + return e.nextElement().getURL();
1.1316 + }
1.1317 + public boolean hasMoreElements() {
1.1318 + return e.hasMoreElements();
1.1319 + }
1.1320 + };
1.1321 + }
1.1322 +
1.1323 + // Returns the URLClassPath that is used for finding system resources.
1.1324 + static URLClassPath getBootstrapClassPath() {
1.1325 + return sun.misc.Launcher.getBootstrapClassPath();
1.1326 + }
1.1327 +
1.1328 +
1.1329 + /**
1.1330 + * Returns an input stream for reading the specified resource.
1.1331 + *
1.1332 + * <p> The search order is described in the documentation for {@link
1.1333 + * #getResource(String)}. </p>
1.1334 + *
1.1335 + * @param name
1.1336 + * The resource name
1.1337 + *
1.1338 + * @return An input stream for reading the resource, or <tt>null</tt>
1.1339 + * if the resource could not be found
1.1340 + *
1.1341 + * @since 1.1
1.1342 + */
1.1343 + public InputStream getResourceAsStream(String name) {
1.1344 + URL url = getResource(name);
1.1345 + try {
1.1346 + return url != null ? url.openStream() : null;
1.1347 + } catch (IOException e) {
1.1348 + return null;
1.1349 + }
1.1350 + }
1.1351 +
1.1352 + /**
1.1353 + * Open for reading, a resource of the specified name from the search path
1.1354 + * used to load classes. This method locates the resource through the
1.1355 + * system class loader (see {@link #getSystemClassLoader()}). </p>
1.1356 + *
1.1357 + * @param name
1.1358 + * The resource name
1.1359 + *
1.1360 + * @return An input stream for reading the resource, or <tt>null</tt>
1.1361 + * if the resource could not be found
1.1362 + *
1.1363 + * @since 1.1
1.1364 + */
1.1365 + public static InputStream getSystemResourceAsStream(String name) {
1.1366 + URL url = getSystemResource(name);
1.1367 + try {
1.1368 + return url != null ? url.openStream() : null;
1.1369 + } catch (IOException e) {
1.1370 + return null;
1.1371 + }
1.1372 + }
1.1373 +
1.1374 +
1.1375 + // -- Hierarchy --
1.1376 +
1.1377 + /**
1.1378 + * Returns the parent class loader for delegation. Some implementations may
1.1379 + * use <tt>null</tt> to represent the bootstrap class loader. This method
1.1380 + * will return <tt>null</tt> in such implementations if this class loader's
1.1381 + * parent is the bootstrap class loader.
1.1382 + *
1.1383 + * <p> If a security manager is present, and the invoker's class loader is
1.1384 + * not <tt>null</tt> and is not an ancestor of this class loader, then this
1.1385 + * method invokes the security manager's {@link
1.1386 + * SecurityManager#checkPermission(java.security.Permission)
1.1387 + * <tt>checkPermission</tt>} method with a {@link
1.1388 + * RuntimePermission#RuntimePermission(String)
1.1389 + * <tt>RuntimePermission("getClassLoader")</tt>} permission to verify
1.1390 + * access to the parent class loader is permitted. If not, a
1.1391 + * <tt>SecurityException</tt> will be thrown. </p>
1.1392 + *
1.1393 + * @return The parent <tt>ClassLoader</tt>
1.1394 + *
1.1395 + * @throws SecurityException
1.1396 + * If a security manager exists and its <tt>checkPermission</tt>
1.1397 + * method doesn't allow access to this class loader's parent class
1.1398 + * loader.
1.1399 + *
1.1400 + * @since 1.2
1.1401 + */
1.1402 + public final ClassLoader getParent() {
1.1403 + if (parent == null)
1.1404 + return null;
1.1405 + SecurityManager sm = System.getSecurityManager();
1.1406 + if (sm != null) {
1.1407 + ClassLoader ccl = getCallerClassLoader();
1.1408 + if (ccl != null && !isAncestor(ccl)) {
1.1409 + sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
1.1410 + }
1.1411 + }
1.1412 + return parent;
1.1413 + }
1.1414 +
1.1415 + /**
1.1416 + * Returns the system class loader for delegation. This is the default
1.1417 + * delegation parent for new <tt>ClassLoader</tt> instances, and is
1.1418 + * typically the class loader used to start the application.
1.1419 + *
1.1420 + * <p> This method is first invoked early in the runtime's startup
1.1421 + * sequence, at which point it creates the system class loader and sets it
1.1422 + * as the context class loader of the invoking <tt>Thread</tt>.
1.1423 + *
1.1424 + * <p> The default system class loader is an implementation-dependent
1.1425 + * instance of this class.
1.1426 + *
1.1427 + * <p> If the system property "<tt>java.system.class.loader</tt>" is defined
1.1428 + * when this method is first invoked then the value of that property is
1.1429 + * taken to be the name of a class that will be returned as the system
1.1430 + * class loader. The class is loaded using the default system class loader
1.1431 + * and must define a public constructor that takes a single parameter of
1.1432 + * type <tt>ClassLoader</tt> which is used as the delegation parent. An
1.1433 + * instance is then created using this constructor with the default system
1.1434 + * class loader as the parameter. The resulting class loader is defined
1.1435 + * to be the system class loader.
1.1436 + *
1.1437 + * <p> If a security manager is present, and the invoker's class loader is
1.1438 + * not <tt>null</tt> and the invoker's class loader is not the same as or
1.1439 + * an ancestor of the system class loader, then this method invokes the
1.1440 + * security manager's {@link
1.1441 + * SecurityManager#checkPermission(java.security.Permission)
1.1442 + * <tt>checkPermission</tt>} method with a {@link
1.1443 + * RuntimePermission#RuntimePermission(String)
1.1444 + * <tt>RuntimePermission("getClassLoader")</tt>} permission to verify
1.1445 + * access to the system class loader. If not, a
1.1446 + * <tt>SecurityException</tt> will be thrown. </p>
1.1447 + *
1.1448 + * @return The system <tt>ClassLoader</tt> for delegation, or
1.1449 + * <tt>null</tt> if none
1.1450 + *
1.1451 + * @throws SecurityException
1.1452 + * If a security manager exists and its <tt>checkPermission</tt>
1.1453 + * method doesn't allow access to the system class loader.
1.1454 + *
1.1455 + * @throws IllegalStateException
1.1456 + * If invoked recursively during the construction of the class
1.1457 + * loader specified by the "<tt>java.system.class.loader</tt>"
1.1458 + * property.
1.1459 + *
1.1460 + * @throws Error
1.1461 + * If the system property "<tt>java.system.class.loader</tt>"
1.1462 + * is defined but the named class could not be loaded, the
1.1463 + * provider class does not define the required constructor, or an
1.1464 + * exception is thrown by that constructor when it is invoked. The
1.1465 + * underlying cause of the error can be retrieved via the
1.1466 + * {@link Throwable#getCause()} method.
1.1467 + *
1.1468 + * @revised 1.4
1.1469 + */
1.1470 + public static ClassLoader getSystemClassLoader() {
1.1471 + initSystemClassLoader();
1.1472 + if (scl == null) {
1.1473 + return null;
1.1474 + }
1.1475 + SecurityManager sm = System.getSecurityManager();
1.1476 + if (sm != null) {
1.1477 + ClassLoader ccl = getCallerClassLoader();
1.1478 + if (ccl != null && ccl != scl && !scl.isAncestor(ccl)) {
1.1479 + sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
1.1480 + }
1.1481 + }
1.1482 + return scl;
1.1483 + }
1.1484 +
1.1485 + private static synchronized void initSystemClassLoader() {
1.1486 + if (!sclSet) {
1.1487 + if (scl != null)
1.1488 + throw new IllegalStateException("recursive invocation");
1.1489 + sun.misc.Launcher l = sun.misc.Launcher.getLauncher();
1.1490 + if (l != null) {
1.1491 + Throwable oops = null;
1.1492 + scl = l.getClassLoader();
1.1493 + try {
1.1494 + scl = AccessController.doPrivileged(
1.1495 + new SystemClassLoaderAction(scl));
1.1496 + } catch (PrivilegedActionException pae) {
1.1497 + oops = pae.getCause();
1.1498 + if (oops instanceof InvocationTargetException) {
1.1499 + oops = oops.getCause();
1.1500 + }
1.1501 + }
1.1502 + if (oops != null) {
1.1503 + if (oops instanceof Error) {
1.1504 + throw (Error) oops;
1.1505 + } else {
1.1506 + // wrap the exception
1.1507 + throw new Error(oops);
1.1508 + }
1.1509 + }
1.1510 + }
1.1511 + sclSet = true;
1.1512 + }
1.1513 + }
1.1514 +
1.1515 + // Returns true if the specified class loader can be found in this class
1.1516 + // loader's delegation chain.
1.1517 + boolean isAncestor(ClassLoader cl) {
1.1518 + ClassLoader acl = this;
1.1519 + do {
1.1520 + acl = acl.parent;
1.1521 + if (cl == acl) {
1.1522 + return true;
1.1523 + }
1.1524 + } while (acl != null);
1.1525 + return false;
1.1526 + }
1.1527 +
1.1528 + // Returns the invoker's class loader, or null if none.
1.1529 + // NOTE: This must always be invoked when there is exactly one intervening
1.1530 + // frame from the core libraries on the stack between this method's
1.1531 + // invocation and the desired invoker.
1.1532 + static ClassLoader getCallerClassLoader() {
1.1533 + // NOTE use of more generic Reflection.getCallerClass()
1.1534 + Class caller = Reflection.getCallerClass(3);
1.1535 + // This can be null if the VM is requesting it
1.1536 + if (caller == null) {
1.1537 + return null;
1.1538 + }
1.1539 + // Circumvent security check since this is package-private
1.1540 + return caller.getClassLoader0();
1.1541 + }
1.1542 +
1.1543 + // The class loader for the system
1.1544 + // @GuardedBy("ClassLoader.class")
1.1545 + private static ClassLoader scl;
1.1546 +
1.1547 + // Set to true once the system class loader has been set
1.1548 + // @GuardedBy("ClassLoader.class")
1.1549 + private static boolean sclSet;
1.1550 +
1.1551 +
1.1552 + // -- Package --
1.1553 +
1.1554 + /**
1.1555 + * Defines a package by name in this <tt>ClassLoader</tt>. This allows
1.1556 + * class loaders to define the packages for their classes. Packages must
1.1557 + * be created before the class is defined, and package names must be
1.1558 + * unique within a class loader and cannot be redefined or changed once
1.1559 + * created. </p>
1.1560 + *
1.1561 + * @param name
1.1562 + * The package name
1.1563 + *
1.1564 + * @param specTitle
1.1565 + * The specification title
1.1566 + *
1.1567 + * @param specVersion
1.1568 + * The specification version
1.1569 + *
1.1570 + * @param specVendor
1.1571 + * The specification vendor
1.1572 + *
1.1573 + * @param implTitle
1.1574 + * The implementation title
1.1575 + *
1.1576 + * @param implVersion
1.1577 + * The implementation version
1.1578 + *
1.1579 + * @param implVendor
1.1580 + * The implementation vendor
1.1581 + *
1.1582 + * @param sealBase
1.1583 + * If not <tt>null</tt>, then this package is sealed with
1.1584 + * respect to the given code source {@link java.net.URL
1.1585 + * <tt>URL</tt>} object. Otherwise, the package is not sealed.
1.1586 + *
1.1587 + * @return The newly defined <tt>Package</tt> object
1.1588 + *
1.1589 + * @throws IllegalArgumentException
1.1590 + * If package name duplicates an existing package either in this
1.1591 + * class loader or one of its ancestors
1.1592 + *
1.1593 + * @since 1.2
1.1594 + */
1.1595 + protected Package definePackage(String name, String specTitle,
1.1596 + String specVersion, String specVendor,
1.1597 + String implTitle, String implVersion,
1.1598 + String implVendor, URL sealBase)
1.1599 + throws IllegalArgumentException
1.1600 + {
1.1601 + synchronized (packages) {
1.1602 + Package pkg = getPackage(name);
1.1603 + if (pkg != null) {
1.1604 + throw new IllegalArgumentException(name);
1.1605 + }
1.1606 + pkg = new Package(name, specTitle, specVersion, specVendor,
1.1607 + implTitle, implVersion, implVendor,
1.1608 + sealBase, this);
1.1609 + packages.put(name, pkg);
1.1610 + return pkg;
1.1611 + }
1.1612 + }
1.1613 +
1.1614 + /**
1.1615 + * Returns a <tt>Package</tt> that has been defined by this class loader
1.1616 + * or any of its ancestors. </p>
1.1617 + *
1.1618 + * @param name
1.1619 + * The package name
1.1620 + *
1.1621 + * @return The <tt>Package</tt> corresponding to the given name, or
1.1622 + * <tt>null</tt> if not found
1.1623 + *
1.1624 + * @since 1.2
1.1625 + */
1.1626 + protected Package getPackage(String name) {
1.1627 + Package pkg;
1.1628 + synchronized (packages) {
1.1629 + pkg = packages.get(name);
1.1630 + }
1.1631 + if (pkg == null) {
1.1632 + if (parent != null) {
1.1633 + pkg = parent.getPackage(name);
1.1634 + } else {
1.1635 + pkg = Package.getSystemPackage(name);
1.1636 + }
1.1637 + if (pkg != null) {
1.1638 + synchronized (packages) {
1.1639 + Package pkg2 = packages.get(name);
1.1640 + if (pkg2 == null) {
1.1641 + packages.put(name, pkg);
1.1642 + } else {
1.1643 + pkg = pkg2;
1.1644 + }
1.1645 + }
1.1646 + }
1.1647 + }
1.1648 + return pkg;
1.1649 + }
1.1650 +
1.1651 + /**
1.1652 + * Returns all of the <tt>Packages</tt> defined by this class loader and
1.1653 + * its ancestors. </p>
1.1654 + *
1.1655 + * @return The array of <tt>Package</tt> objects defined by this
1.1656 + * <tt>ClassLoader</tt>
1.1657 + *
1.1658 + * @since 1.2
1.1659 + */
1.1660 + protected Package[] getPackages() {
1.1661 + Map<String, Package> map;
1.1662 + synchronized (packages) {
1.1663 + map = new HashMap<>(packages);
1.1664 + }
1.1665 + Package[] pkgs;
1.1666 + if (parent != null) {
1.1667 + pkgs = parent.getPackages();
1.1668 + } else {
1.1669 + pkgs = Package.getSystemPackages();
1.1670 + }
1.1671 + if (pkgs != null) {
1.1672 + for (int i = 0; i < pkgs.length; i++) {
1.1673 + String pkgName = pkgs[i].getName();
1.1674 + if (map.get(pkgName) == null) {
1.1675 + map.put(pkgName, pkgs[i]);
1.1676 + }
1.1677 + }
1.1678 + }
1.1679 + return map.values().toArray(new Package[map.size()]);
1.1680 + }
1.1681 +
1.1682 +
1.1683 + // -- Native library access --
1.1684 +
1.1685 + /**
1.1686 + * Returns the absolute path name of a native library. The VM invokes this
1.1687 + * method to locate the native libraries that belong to classes loaded with
1.1688 + * this class loader. If this method returns <tt>null</tt>, the VM
1.1689 + * searches the library along the path specified as the
1.1690 + * "<tt>java.library.path</tt>" property. </p>
1.1691 + *
1.1692 + * @param libname
1.1693 + * The library name
1.1694 + *
1.1695 + * @return The absolute path of the native library
1.1696 + *
1.1697 + * @see System#loadLibrary(String)
1.1698 + * @see System#mapLibraryName(String)
1.1699 + *
1.1700 + * @since 1.2
1.1701 + */
1.1702 + protected String findLibrary(String libname) {
1.1703 + return null;
1.1704 + }
1.1705 +
1.1706 + /**
1.1707 + * The inner class NativeLibrary denotes a loaded native library instance.
1.1708 + * Every classloader contains a vector of loaded native libraries in the
1.1709 + * private field <tt>nativeLibraries</tt>. The native libraries loaded
1.1710 + * into the system are entered into the <tt>systemNativeLibraries</tt>
1.1711 + * vector.
1.1712 + *
1.1713 + * <p> Every native library requires a particular version of JNI. This is
1.1714 + * denoted by the private <tt>jniVersion</tt> field. This field is set by
1.1715 + * the VM when it loads the library, and used by the VM to pass the correct
1.1716 + * version of JNI to the native methods. </p>
1.1717 + *
1.1718 + * @see ClassLoader
1.1719 + * @since 1.2
1.1720 + */
1.1721 + static class NativeLibrary {
1.1722 + // opaque handle to native library, used in native code.
1.1723 + long handle;
1.1724 + // the version of JNI environment the native library requires.
1.1725 + private int jniVersion;
1.1726 + // the class from which the library is loaded, also indicates
1.1727 + // the loader this native library belongs.
1.1728 + private Class fromClass;
1.1729 + // the canonicalized name of the native library.
1.1730 + String name;
1.1731 +
1.1732 + native void load(String name);
1.1733 + native long find(String name);
1.1734 + native void unload();
1.1735 +
1.1736 + public NativeLibrary(Class fromClass, String name) {
1.1737 + this.name = name;
1.1738 + this.fromClass = fromClass;
1.1739 + }
1.1740 +
1.1741 + protected void finalize() {
1.1742 + synchronized (loadedLibraryNames) {
1.1743 + if (fromClass.getClassLoader() != null && handle != 0) {
1.1744 + /* remove the native library name */
1.1745 + int size = loadedLibraryNames.size();
1.1746 + for (int i = 0; i < size; i++) {
1.1747 + if (name.equals(loadedLibraryNames.elementAt(i))) {
1.1748 + loadedLibraryNames.removeElementAt(i);
1.1749 + break;
1.1750 + }
1.1751 + }
1.1752 + /* unload the library. */
1.1753 + ClassLoader.nativeLibraryContext.push(this);
1.1754 + try {
1.1755 + unload();
1.1756 + } finally {
1.1757 + ClassLoader.nativeLibraryContext.pop();
1.1758 + }
1.1759 + }
1.1760 + }
1.1761 + }
1.1762 + // Invoked in the VM to determine the context class in
1.1763 + // JNI_Load/JNI_Unload
1.1764 + static Class getFromClass() {
1.1765 + return ClassLoader.nativeLibraryContext.peek().fromClass;
1.1766 + }
1.1767 + }
1.1768 +
1.1769 + // All native library names we've loaded.
1.1770 + private static Vector<String> loadedLibraryNames = new Vector<>();
1.1771 +
1.1772 + // Native libraries belonging to system classes.
1.1773 + private static Vector<NativeLibrary> systemNativeLibraries
1.1774 + = new Vector<>();
1.1775 +
1.1776 + // Native libraries associated with the class loader.
1.1777 + private Vector<NativeLibrary> nativeLibraries = new Vector<>();
1.1778 +
1.1779 + // native libraries being loaded/unloaded.
1.1780 + private static Stack<NativeLibrary> nativeLibraryContext = new Stack<>();
1.1781 +
1.1782 + // The paths searched for libraries
1.1783 + private static String usr_paths[];
1.1784 + private static String sys_paths[];
1.1785 +
1.1786 + private static String[] initializePath(String propname) {
1.1787 + String ldpath = System.getProperty(propname, "");
1.1788 + String ps = File.pathSeparator;
1.1789 + int ldlen = ldpath.length();
1.1790 + int i, j, n;
1.1791 + // Count the separators in the path
1.1792 + i = ldpath.indexOf(ps);
1.1793 + n = 0;
1.1794 + while (i >= 0) {
1.1795 + n++;
1.1796 + i = ldpath.indexOf(ps, i + 1);
1.1797 + }
1.1798 +
1.1799 + // allocate the array of paths - n :'s = n + 1 path elements
1.1800 + String[] paths = new String[n + 1];
1.1801 +
1.1802 + // Fill the array with paths from the ldpath
1.1803 + n = i = 0;
1.1804 + j = ldpath.indexOf(ps);
1.1805 + while (j >= 0) {
1.1806 + if (j - i > 0) {
1.1807 + paths[n++] = ldpath.substring(i, j);
1.1808 + } else if (j - i == 0) {
1.1809 + paths[n++] = ".";
1.1810 + }
1.1811 + i = j + 1;
1.1812 + j = ldpath.indexOf(ps, i);
1.1813 + }
1.1814 + paths[n] = ldpath.substring(i, ldlen);
1.1815 + return paths;
1.1816 + }
1.1817 +
1.1818 + // Invoked in the java.lang.Runtime class to implement load and loadLibrary.
1.1819 + static void loadLibrary(Class fromClass, String name,
1.1820 + boolean isAbsolute) {
1.1821 + ClassLoader loader =
1.1822 + (fromClass == null) ? null : fromClass.getClassLoader();
1.1823 + if (sys_paths == null) {
1.1824 + usr_paths = initializePath("java.library.path");
1.1825 + sys_paths = initializePath("sun.boot.library.path");
1.1826 + }
1.1827 + if (isAbsolute) {
1.1828 + if (loadLibrary0(fromClass, new File(name))) {
1.1829 + return;
1.1830 + }
1.1831 + throw new UnsatisfiedLinkError("Can't load library: " + name);
1.1832 + }
1.1833 + if (loader != null) {
1.1834 + String libfilename = loader.findLibrary(name);
1.1835 + if (libfilename != null) {
1.1836 + File libfile = new File(libfilename);
1.1837 + if (!libfile.isAbsolute()) {
1.1838 + throw new UnsatisfiedLinkError(
1.1839 + "ClassLoader.findLibrary failed to return an absolute path: " + libfilename);
1.1840 + }
1.1841 + if (loadLibrary0(fromClass, libfile)) {
1.1842 + return;
1.1843 + }
1.1844 + throw new UnsatisfiedLinkError("Can't load " + libfilename);
1.1845 + }
1.1846 + }
1.1847 + for (int i = 0 ; i < sys_paths.length ; i++) {
1.1848 + File libfile = new File(sys_paths[i], System.mapLibraryName(name));
1.1849 + if (loadLibrary0(fromClass, libfile)) {
1.1850 + return;
1.1851 + }
1.1852 + }
1.1853 + if (loader != null) {
1.1854 + for (int i = 0 ; i < usr_paths.length ; i++) {
1.1855 + File libfile = new File(usr_paths[i],
1.1856 + System.mapLibraryName(name));
1.1857 + if (loadLibrary0(fromClass, libfile)) {
1.1858 + return;
1.1859 + }
1.1860 + }
1.1861 + }
1.1862 + // Oops, it failed
1.1863 + throw new UnsatisfiedLinkError("no " + name + " in java.library.path");
1.1864 + }
1.1865 +
1.1866 + private static boolean loadLibrary0(Class fromClass, final File file) {
1.1867 + boolean exists = AccessController.doPrivileged(
1.1868 + new PrivilegedAction<Object>() {
1.1869 + public Object run() {
1.1870 + return file.exists() ? Boolean.TRUE : null;
1.1871 + }})
1.1872 + != null;
1.1873 + if (!exists) {
1.1874 + return false;
1.1875 + }
1.1876 + String name;
1.1877 + try {
1.1878 + name = file.getCanonicalPath();
1.1879 + } catch (IOException e) {
1.1880 + return false;
1.1881 + }
1.1882 + ClassLoader loader =
1.1883 + (fromClass == null) ? null : fromClass.getClassLoader();
1.1884 + Vector<NativeLibrary> libs =
1.1885 + loader != null ? loader.nativeLibraries : systemNativeLibraries;
1.1886 + synchronized (libs) {
1.1887 + int size = libs.size();
1.1888 + for (int i = 0; i < size; i++) {
1.1889 + NativeLibrary lib = libs.elementAt(i);
1.1890 + if (name.equals(lib.name)) {
1.1891 + return true;
1.1892 + }
1.1893 + }
1.1894 +
1.1895 + synchronized (loadedLibraryNames) {
1.1896 + if (loadedLibraryNames.contains(name)) {
1.1897 + throw new UnsatisfiedLinkError
1.1898 + ("Native Library " +
1.1899 + name +
1.1900 + " already loaded in another classloader");
1.1901 + }
1.1902 + /* If the library is being loaded (must be by the same thread,
1.1903 + * because Runtime.load and Runtime.loadLibrary are
1.1904 + * synchronous). The reason is can occur is that the JNI_OnLoad
1.1905 + * function can cause another loadLibrary invocation.
1.1906 + *
1.1907 + * Thus we can use a static stack to hold the list of libraries
1.1908 + * we are loading.
1.1909 + *
1.1910 + * If there is a pending load operation for the library, we
1.1911 + * immediately return success; otherwise, we raise
1.1912 + * UnsatisfiedLinkError.
1.1913 + */
1.1914 + int n = nativeLibraryContext.size();
1.1915 + for (int i = 0; i < n; i++) {
1.1916 + NativeLibrary lib = nativeLibraryContext.elementAt(i);
1.1917 + if (name.equals(lib.name)) {
1.1918 + if (loader == lib.fromClass.getClassLoader()) {
1.1919 + return true;
1.1920 + } else {
1.1921 + throw new UnsatisfiedLinkError
1.1922 + ("Native Library " +
1.1923 + name +
1.1924 + " is being loaded in another classloader");
1.1925 + }
1.1926 + }
1.1927 + }
1.1928 + NativeLibrary lib = new NativeLibrary(fromClass, name);
1.1929 + nativeLibraryContext.push(lib);
1.1930 + try {
1.1931 + lib.load(name);
1.1932 + } finally {
1.1933 + nativeLibraryContext.pop();
1.1934 + }
1.1935 + if (lib.handle != 0) {
1.1936 + loadedLibraryNames.addElement(name);
1.1937 + libs.addElement(lib);
1.1938 + return true;
1.1939 + }
1.1940 + return false;
1.1941 + }
1.1942 + }
1.1943 + }
1.1944 +
1.1945 + // Invoked in the VM class linking code.
1.1946 + static long findNative(ClassLoader loader, String name) {
1.1947 + Vector<NativeLibrary> libs =
1.1948 + loader != null ? loader.nativeLibraries : systemNativeLibraries;
1.1949 + synchronized (libs) {
1.1950 + int size = libs.size();
1.1951 + for (int i = 0; i < size; i++) {
1.1952 + NativeLibrary lib = libs.elementAt(i);
1.1953 + long entry = lib.find(name);
1.1954 + if (entry != 0)
1.1955 + return entry;
1.1956 + }
1.1957 + }
1.1958 + return 0;
1.1959 + }
1.1960 +
1.1961 +
1.1962 + // -- Assertion management --
1.1963 +
1.1964 + final Object assertionLock;
1.1965 +
1.1966 + // The default toggle for assertion checking.
1.1967 + // @GuardedBy("assertionLock")
1.1968 + private boolean defaultAssertionStatus = false;
1.1969 +
1.1970 + // Maps String packageName to Boolean package default assertion status Note
1.1971 + // that the default package is placed under a null map key. If this field
1.1972 + // is null then we are delegating assertion status queries to the VM, i.e.,
1.1973 + // none of this ClassLoader's assertion status modification methods have
1.1974 + // been invoked.
1.1975 + // @GuardedBy("assertionLock")
1.1976 + private Map<String, Boolean> packageAssertionStatus = null;
1.1977 +
1.1978 + // Maps String fullyQualifiedClassName to Boolean assertionStatus If this
1.1979 + // field is null then we are delegating assertion status queries to the VM,
1.1980 + // i.e., none of this ClassLoader's assertion status modification methods
1.1981 + // have been invoked.
1.1982 + // @GuardedBy("assertionLock")
1.1983 + Map<String, Boolean> classAssertionStatus = null;
1.1984 +
1.1985 + /**
1.1986 + * Sets the default assertion status for this class loader. This setting
1.1987 + * determines whether classes loaded by this class loader and initialized
1.1988 + * in the future will have assertions enabled or disabled by default.
1.1989 + * This setting may be overridden on a per-package or per-class basis by
1.1990 + * invoking {@link #setPackageAssertionStatus(String, boolean)} or {@link
1.1991 + * #setClassAssertionStatus(String, boolean)}. </p>
1.1992 + *
1.1993 + * @param enabled
1.1994 + * <tt>true</tt> if classes loaded by this class loader will
1.1995 + * henceforth have assertions enabled by default, <tt>false</tt>
1.1996 + * if they will have assertions disabled by default.
1.1997 + *
1.1998 + * @since 1.4
1.1999 + */
1.2000 + public void setDefaultAssertionStatus(boolean enabled) {
1.2001 + synchronized (assertionLock) {
1.2002 + if (classAssertionStatus == null)
1.2003 + initializeJavaAssertionMaps();
1.2004 +
1.2005 + defaultAssertionStatus = enabled;
1.2006 + }
1.2007 + }
1.2008 +
1.2009 + /**
1.2010 + * Sets the package default assertion status for the named package. The
1.2011 + * package default assertion status determines the assertion status for
1.2012 + * classes initialized in the future that belong to the named package or
1.2013 + * any of its "subpackages".
1.2014 + *
1.2015 + * <p> A subpackage of a package named p is any package whose name begins
1.2016 + * with "<tt>p.</tt>". For example, <tt>javax.swing.text</tt> is a
1.2017 + * subpackage of <tt>javax.swing</tt>, and both <tt>java.util</tt> and
1.2018 + * <tt>java.lang.reflect</tt> are subpackages of <tt>java</tt>.
1.2019 + *
1.2020 + * <p> In the event that multiple package defaults apply to a given class,
1.2021 + * the package default pertaining to the most specific package takes
1.2022 + * precedence over the others. For example, if <tt>javax.lang</tt> and
1.2023 + * <tt>javax.lang.reflect</tt> both have package defaults associated with
1.2024 + * them, the latter package default applies to classes in
1.2025 + * <tt>javax.lang.reflect</tt>.
1.2026 + *
1.2027 + * <p> Package defaults take precedence over the class loader's default
1.2028 + * assertion status, and may be overridden on a per-class basis by invoking
1.2029 + * {@link #setClassAssertionStatus(String, boolean)}. </p>
1.2030 + *
1.2031 + * @param packageName
1.2032 + * The name of the package whose package default assertion status
1.2033 + * is to be set. A <tt>null</tt> value indicates the unnamed
1.2034 + * package that is "current"
1.2035 + * (see section 7.4.2 of
1.2036 + * <cite>The Java™ Language Specification</cite>.)
1.2037 + *
1.2038 + * @param enabled
1.2039 + * <tt>true</tt> if classes loaded by this classloader and
1.2040 + * belonging to the named package or any of its subpackages will
1.2041 + * have assertions enabled by default, <tt>false</tt> if they will
1.2042 + * have assertions disabled by default.
1.2043 + *
1.2044 + * @since 1.4
1.2045 + */
1.2046 + public void setPackageAssertionStatus(String packageName,
1.2047 + boolean enabled) {
1.2048 + synchronized (assertionLock) {
1.2049 + if (packageAssertionStatus == null)
1.2050 + initializeJavaAssertionMaps();
1.2051 +
1.2052 + packageAssertionStatus.put(packageName, enabled);
1.2053 + }
1.2054 + }
1.2055 +
1.2056 + /**
1.2057 + * Sets the desired assertion status for the named top-level class in this
1.2058 + * class loader and any nested classes contained therein. This setting
1.2059 + * takes precedence over the class loader's default assertion status, and
1.2060 + * over any applicable per-package default. This method has no effect if
1.2061 + * the named class has already been initialized. (Once a class is
1.2062 + * initialized, its assertion status cannot change.)
1.2063 + *
1.2064 + * <p> If the named class is not a top-level class, this invocation will
1.2065 + * have no effect on the actual assertion status of any class. </p>
1.2066 + *
1.2067 + * @param className
1.2068 + * The fully qualified class name of the top-level class whose
1.2069 + * assertion status is to be set.
1.2070 + *
1.2071 + * @param enabled
1.2072 + * <tt>true</tt> if the named class is to have assertions
1.2073 + * enabled when (and if) it is initialized, <tt>false</tt> if the
1.2074 + * class is to have assertions disabled.
1.2075 + *
1.2076 + * @since 1.4
1.2077 + */
1.2078 + public void setClassAssertionStatus(String className, boolean enabled) {
1.2079 + synchronized (assertionLock) {
1.2080 + if (classAssertionStatus == null)
1.2081 + initializeJavaAssertionMaps();
1.2082 +
1.2083 + classAssertionStatus.put(className, enabled);
1.2084 + }
1.2085 + }
1.2086 +
1.2087 + /**
1.2088 + * Sets the default assertion status for this class loader to
1.2089 + * <tt>false</tt> and discards any package defaults or class assertion
1.2090 + * status settings associated with the class loader. This method is
1.2091 + * provided so that class loaders can be made to ignore any command line or
1.2092 + * persistent assertion status settings and "start with a clean slate."
1.2093 + * </p>
1.2094 + *
1.2095 + * @since 1.4
1.2096 + */
1.2097 + public void clearAssertionStatus() {
1.2098 + /*
1.2099 + * Whether or not "Java assertion maps" are initialized, set
1.2100 + * them to empty maps, effectively ignoring any present settings.
1.2101 + */
1.2102 + synchronized (assertionLock) {
1.2103 + classAssertionStatus = new HashMap<>();
1.2104 + packageAssertionStatus = new HashMap<>();
1.2105 + defaultAssertionStatus = false;
1.2106 + }
1.2107 + }
1.2108 +
1.2109 + /**
1.2110 + * Returns the assertion status that would be assigned to the specified
1.2111 + * class if it were to be initialized at the time this method is invoked.
1.2112 + * If the named class has had its assertion status set, the most recent
1.2113 + * setting will be returned; otherwise, if any package default assertion
1.2114 + * status pertains to this class, the most recent setting for the most
1.2115 + * specific pertinent package default assertion status is returned;
1.2116 + * otherwise, this class loader's default assertion status is returned.
1.2117 + * </p>
1.2118 + *
1.2119 + * @param className
1.2120 + * The fully qualified class name of the class whose desired
1.2121 + * assertion status is being queried.
1.2122 + *
1.2123 + * @return The desired assertion status of the specified class.
1.2124 + *
1.2125 + * @see #setClassAssertionStatus(String, boolean)
1.2126 + * @see #setPackageAssertionStatus(String, boolean)
1.2127 + * @see #setDefaultAssertionStatus(boolean)
1.2128 + *
1.2129 + * @since 1.4
1.2130 + */
1.2131 + boolean desiredAssertionStatus(String className) {
1.2132 + synchronized (assertionLock) {
1.2133 + // assert classAssertionStatus != null;
1.2134 + // assert packageAssertionStatus != null;
1.2135 +
1.2136 + // Check for a class entry
1.2137 + Boolean result = classAssertionStatus.get(className);
1.2138 + if (result != null)
1.2139 + return result.booleanValue();
1.2140 +
1.2141 + // Check for most specific package entry
1.2142 + int dotIndex = className.lastIndexOf(".");
1.2143 + if (dotIndex < 0) { // default package
1.2144 + result = packageAssertionStatus.get(null);
1.2145 + if (result != null)
1.2146 + return result.booleanValue();
1.2147 + }
1.2148 + while(dotIndex > 0) {
1.2149 + className = className.substring(0, dotIndex);
1.2150 + result = packageAssertionStatus.get(className);
1.2151 + if (result != null)
1.2152 + return result.booleanValue();
1.2153 + dotIndex = className.lastIndexOf(".", dotIndex-1);
1.2154 + }
1.2155 +
1.2156 + // Return the classloader default
1.2157 + return defaultAssertionStatus;
1.2158 + }
1.2159 + }
1.2160 +
1.2161 + // Set up the assertions with information provided by the VM.
1.2162 + // Note: Should only be called inside a synchronized block
1.2163 + private void initializeJavaAssertionMaps() {
1.2164 + // assert Thread.holdsLock(assertionLock);
1.2165 +
1.2166 + classAssertionStatus = new HashMap<>();
1.2167 + packageAssertionStatus = new HashMap<>();
1.2168 + AssertionStatusDirectives directives = retrieveDirectives();
1.2169 +
1.2170 + for(int i = 0; i < directives.classes.length; i++)
1.2171 + classAssertionStatus.put(directives.classes[i],
1.2172 + directives.classEnabled[i]);
1.2173 +
1.2174 + for(int i = 0; i < directives.packages.length; i++)
1.2175 + packageAssertionStatus.put(directives.packages[i],
1.2176 + directives.packageEnabled[i]);
1.2177 +
1.2178 + defaultAssertionStatus = directives.deflt;
1.2179 + }
1.2180 +
1.2181 + // Retrieves the assertion directives from the VM.
1.2182 + private static native AssertionStatusDirectives retrieveDirectives();
1.2183 +}
1.2184 +
1.2185 +
1.2186 +class SystemClassLoaderAction
1.2187 + implements PrivilegedExceptionAction<ClassLoader> {
1.2188 + private ClassLoader parent;
1.2189 +
1.2190 + SystemClassLoaderAction(ClassLoader parent) {
1.2191 + this.parent = parent;
1.2192 + }
1.2193 +
1.2194 + public ClassLoader run() throws Exception {
1.2195 + String cls = System.getProperty("java.system.class.loader");
1.2196 + if (cls == null) {
1.2197 + return parent;
1.2198 + }
1.2199 +
1.2200 + Constructor ctor = Class.forName(cls, true, parent)
1.2201 + .getDeclaredConstructor(new Class[] { ClassLoader.class });
1.2202 + ClassLoader sys = (ClassLoader) ctor.newInstance(
1.2203 + new Object[] { parent });
1.2204 + Thread.currentThread().setContextClassLoader(sys);
1.2205 + return sys;
1.2206 + }
1.2207 +}