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