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