1 |
/* ClassLoader.java -- responsible for loading classes into the VM |
/* ClassLoader.java -- responsible for loading classes into the VM |
2 |
Copyright (C) 1998, 1999, 2001, 2002, 2003 Free Software Foundation, Inc. |
Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. |
3 |
|
|
4 |
This file is part of GNU Classpath. |
This file is part of GNU Classpath. |
5 |
|
|
44 |
import java.io.IOException; |
import java.io.IOException; |
45 |
import java.io.InputStream; |
import java.io.InputStream; |
46 |
import java.net.URL; |
import java.net.URL; |
47 |
|
import java.nio.ByteBuffer; |
48 |
import java.security.CodeSource; |
import java.security.CodeSource; |
49 |
import java.security.PermissionCollection; |
import java.security.PermissionCollection; |
50 |
import java.security.Policy; |
import java.security.Policy; |
113 |
* @author Eric Blake <ebb9@email.byu.edu> |
* @author Eric Blake <ebb9@email.byu.edu> |
114 |
* @see Class |
* @see Class |
115 |
* @since 1.0 |
* @since 1.0 |
|
* @status still missing 1.4 functionality |
|
116 |
*/ |
*/ |
117 |
public abstract class ClassLoader |
public abstract class ClassLoader |
118 |
{ |
{ |
122 |
* is not private in order to allow native code (and trusted subclasses) |
* is not private in order to allow native code (and trusted subclasses) |
123 |
* access to this field. |
* access to this field. |
124 |
*/ |
*/ |
125 |
final Map loadedClasses = new HashMap(); |
final HashMap<String, Class<?>> loadedClasses = new HashMap<String, Class<?>>(); |
126 |
|
|
127 |
/** |
/** |
128 |
* All packages defined by this classloader. It is not private in order to |
* All packages defined by this classloader. It is not private in order to |
129 |
* allow native code (and trusted subclasses) access to this field. |
* allow native code (and trusted subclasses) access to this field. |
130 |
*/ |
*/ |
131 |
final Map definedPackages = new HashMap(); |
final HashMap<String, Package> definedPackages = new HashMap<String, Package>(); |
132 |
|
|
133 |
/** |
/** |
134 |
* The classloader that is consulted before this classloader. |
* The classloader that is consulted before this classloader. |
190 |
* by the null key. This map must be synchronized on this instance. |
* by the null key. This map must be synchronized on this instance. |
191 |
*/ |
*/ |
192 |
// Package visible for use by Class. |
// Package visible for use by Class. |
193 |
Map packageAssertionStatus; |
Map<String, Boolean> packageAssertionStatus; |
194 |
|
|
195 |
/** |
/** |
196 |
* The command-line state of the class assertion status overrides. This |
* The command-line state of the class assertion status overrides. This |
197 |
* map is never modified, so it does not need to be synchronized. |
* map is never modified, so it does not need to be synchronized. |
198 |
*/ |
*/ |
199 |
// Package visible for use by Class. |
// Package visible for use by Class. |
200 |
static final Map systemClassAssertionStatus |
static final Map<String, Boolean> systemClassAssertionStatus |
201 |
= VMClassLoader.classAssertionStatus(); |
= VMClassLoader.classAssertionStatus(); |
202 |
|
|
203 |
/** |
/** |
207 |
* instance. |
* instance. |
208 |
*/ |
*/ |
209 |
// Package visible for use by Class. |
// Package visible for use by Class. |
210 |
Map classAssertionStatus; |
Map<String, Boolean> classAssertionStatus; |
211 |
|
|
212 |
/** |
/** |
213 |
* Create a new ClassLoader with as parent the system classloader. There |
* Create a new ClassLoader with as parent the system classloader. There |
255 |
* @return the loaded class |
* @return the loaded class |
256 |
* @throws ClassNotFoundException if the class cannot be found |
* @throws ClassNotFoundException if the class cannot be found |
257 |
*/ |
*/ |
258 |
public Class loadClass(String name) throws ClassNotFoundException |
public Class<?> loadClass(String name) throws ClassNotFoundException |
259 |
{ |
{ |
260 |
return loadClass(name, false); |
return loadClass(name, false); |
261 |
} |
} |
280 |
* @return the loaded class |
* @return the loaded class |
281 |
* @throws ClassNotFoundException if the class cannot be found |
* @throws ClassNotFoundException if the class cannot be found |
282 |
*/ |
*/ |
283 |
protected synchronized Class loadClass(String name, boolean resolve) |
protected synchronized Class<?> loadClass(String name, boolean resolve) |
284 |
throws ClassNotFoundException |
throws ClassNotFoundException |
285 |
{ |
{ |
286 |
// Have we already loaded this class? |
// Have we already loaded this class? |
287 |
Class c = findLoadedClass(name); |
Class<?> c = findLoadedClass(name); |
288 |
if (c != null) |
if (c != null) |
289 |
return c; |
return c; |
290 |
|
|
354 |
* @throws ClassNotFoundException when the class can not be found |
* @throws ClassNotFoundException when the class can not be found |
355 |
* @since 1.2 |
* @since 1.2 |
356 |
*/ |
*/ |
357 |
protected Class findClass(String name) throws ClassNotFoundException |
protected Class<?> findClass(String name) throws ClassNotFoundException |
358 |
{ |
{ |
359 |
throw new ClassNotFoundException(name); |
throw new ClassNotFoundException(name); |
360 |
} |
} |
372 |
* offset + len exceeds data |
* offset + len exceeds data |
373 |
* @deprecated use {@link #defineClass(String, byte[], int, int)} instead |
* @deprecated use {@link #defineClass(String, byte[], int, int)} instead |
374 |
*/ |
*/ |
375 |
protected final Class defineClass(byte[] data, int offset, int len) |
protected final Class<?> defineClass(byte[] data, int offset, int len) |
376 |
throws ClassFormatError |
throws ClassFormatError |
377 |
{ |
{ |
378 |
return defineClass(null, data, offset, len); |
return defineClass(null, data, offset, len); |
397 |
* @throws SecurityException if name starts with "java." |
* @throws SecurityException if name starts with "java." |
398 |
* @since 1.1 |
* @since 1.1 |
399 |
*/ |
*/ |
400 |
protected final Class defineClass(String name, byte[] data, int offset, |
protected final Class<?> defineClass(String name, byte[] data, int offset, |
401 |
int len) throws ClassFormatError |
int len) throws ClassFormatError |
402 |
{ |
{ |
403 |
return defineClass(name, data, offset, len, null); |
return defineClass(name, data, offset, len, null); |
404 |
} |
} |
426 |
* do not match up |
* do not match up |
427 |
* @since 1.2 |
* @since 1.2 |
428 |
*/ |
*/ |
429 |
protected final synchronized Class defineClass(String name, byte[] data, |
protected final synchronized Class<?> defineClass(String name, byte[] data, |
430 |
int offset, int len, |
int offset, int len, |
431 |
ProtectionDomain domain) |
ProtectionDomain domain) |
432 |
throws ClassFormatError |
throws ClassFormatError |
433 |
{ |
{ |
434 |
if (domain == null) |
if (domain == null) |
435 |
domain = defaultProtectionDomain; |
domain = defaultProtectionDomain; |
436 |
if (! initialized) |
if (! initialized) |
437 |
throw new SecurityException("attempt to define class from uninitialized class loader"); |
throw new SecurityException("attempt to define class from uninitialized class loader"); |
438 |
Class retval = VMClassLoader.defineClass(this, name, data, |
Class<?> retval = VMClassLoader.defineClass(this, name, data, |
439 |
offset, len, domain); |
offset, len, domain); |
440 |
loadedClasses.put(retval.getName(), retval); |
loadedClasses.put(retval.getName(), retval); |
441 |
return retval; |
return retval; |
442 |
} |
} |
443 |
|
|
444 |
|
protected final Class<?> defineClass(String name, ByteBuffer buf, |
445 |
|
ProtectionDomain domain) |
446 |
|
throws ClassFormatError |
447 |
|
{ |
448 |
|
byte[] data = new byte[buf.remaining()]; |
449 |
|
buf.get(data); |
450 |
|
return defineClass(name, data, 0, data.length, domain); |
451 |
|
} |
452 |
|
|
453 |
/** |
/** |
454 |
* Links the class, if that has not already been done. Linking basically |
* Links the class, if that has not already been done. Linking basically |
455 |
* resolves all references to other classes made by this class. |
* resolves all references to other classes made by this class. |
458 |
* @throws NullPointerException if c is null |
* @throws NullPointerException if c is null |
459 |
* @throws LinkageError if linking fails |
* @throws LinkageError if linking fails |
460 |
*/ |
*/ |
461 |
protected final void resolveClass(Class c) |
protected final void resolveClass(Class<?> c) |
462 |
{ |
{ |
463 |
VMClassLoader.resolveClass(c); |
VMClassLoader.resolveClass(c); |
464 |
} |
} |
472 |
* @return the found class |
* @return the found class |
473 |
* @throws ClassNotFoundException if the class cannot be found |
* @throws ClassNotFoundException if the class cannot be found |
474 |
*/ |
*/ |
475 |
protected final Class findSystemClass(String name) |
protected final Class<?> findSystemClass(String name) |
476 |
throws ClassNotFoundException |
throws ClassNotFoundException |
477 |
{ |
{ |
478 |
return Class.forName(name, false, systemClassLoader); |
return Class.forName(name, false, systemClassLoader); |
494 |
SecurityManager sm = System.getSecurityManager(); |
SecurityManager sm = System.getSecurityManager(); |
495 |
if (sm != null) |
if (sm != null) |
496 |
{ |
{ |
497 |
Class c = VMSecurityManager.getClassContext()[1]; |
Class<?> c = VMSecurityManager.getClassContext()[1]; |
498 |
ClassLoader cl = c.getClassLoader(); |
ClassLoader cl = c.getClassLoader(); |
499 |
if (cl != null && ! cl.isAncestorOf(this)) |
if (cl != null && ! cl.isAncestorOf(this)) |
500 |
sm.checkPermission(new RuntimePermission("getClassLoader")); |
sm.checkPermission(new RuntimePermission("getClassLoader")); |
510 |
* @param signers the signers to set |
* @param signers the signers to set |
511 |
* @since 1.1 |
* @since 1.1 |
512 |
*/ |
*/ |
513 |
protected final void setSigners(Class c, Object[] signers) |
protected final void setSigners(Class<?> c, Object[] signers) |
514 |
{ |
{ |
515 |
c.setSigners(signers); |
c.setSigners(signers); |
516 |
} |
} |
522 |
* @return the found Class, or null if it is not found |
* @return the found Class, or null if it is not found |
523 |
* @since 1.1 |
* @since 1.1 |
524 |
*/ |
*/ |
525 |
protected final synchronized Class findLoadedClass(String name) |
protected final synchronized Class<?> findLoadedClass(String name) |
526 |
{ |
{ |
527 |
// NOTE: If the VM is keeping its own cache, it may make sense to have |
// NOTE: If the VM is keeping its own cache, it may make sense to have |
528 |
// this method be native. |
// this method be native. |
529 |
return (Class) loadedClasses.get(name); |
return loadedClasses.get(name); |
530 |
} |
} |
531 |
|
|
532 |
/** |
/** |
577 |
* @throws IOException if I/O errors occur in the process |
* @throws IOException if I/O errors occur in the process |
578 |
* @since 1.2 |
* @since 1.2 |
579 |
*/ |
*/ |
580 |
public final Enumeration getResources(String name) throws IOException |
public final Enumeration<URL> getResources(String name) throws IOException |
581 |
{ |
{ |
582 |
Enumeration parentResources; |
Enumeration<URL> parentResources; |
583 |
if (parent == null) |
if (parent == null) |
584 |
parentResources = VMClassLoader.getResources(name); |
parentResources = VMClassLoader.getResources(name); |
585 |
else |
else |
586 |
parentResources = parent.getResources(name); |
parentResources = parent.getResources(name); |
587 |
return new DoubleEnumeration(parentResources, findResources(name)); |
return new DoubleEnumeration<URL>(parentResources, findResources(name)); |
588 |
} |
} |
589 |
|
|
590 |
/** |
/** |
604 |
* @throws IOException if I/O errors occur in the process |
* @throws IOException if I/O errors occur in the process |
605 |
* @since 1.2 |
* @since 1.2 |
606 |
*/ |
*/ |
607 |
protected Enumeration findResources(String name) throws IOException |
protected Enumeration<URL> findResources(String name) throws IOException |
608 |
{ |
{ |
609 |
return EmptyEnumeration.getInstance(); |
return (Enumeration<URL>) EmptyEnumeration.getInstance(); |
610 |
} |
} |
611 |
|
|
612 |
/** |
/** |
651 |
* @throws IOException if I/O errors occur in the process |
* @throws IOException if I/O errors occur in the process |
652 |
* @since 1.2 |
* @since 1.2 |
653 |
*/ |
*/ |
654 |
public static Enumeration getSystemResources(String name) throws IOException |
public static Enumeration<URL> getSystemResources(String name) |
655 |
|
throws IOException |
656 |
{ |
{ |
657 |
return systemClassLoader.getResources(name); |
return systemClassLoader.getResources(name); |
658 |
} |
} |
738 |
SecurityManager sm = System.getSecurityManager(); |
SecurityManager sm = System.getSecurityManager(); |
739 |
if (sm != null) |
if (sm != null) |
740 |
{ |
{ |
741 |
Class c = VMSecurityManager.getClassContext()[1]; |
Class<?> c = VMSecurityManager.getClassContext()[1]; |
742 |
ClassLoader cl = c.getClassLoader(); |
ClassLoader cl = c.getClassLoader(); |
743 |
if (cl != null && cl != systemClassLoader) |
if (cl != null && cl != systemClassLoader) |
744 |
sm.checkPermission(new RuntimePermission("getClassLoader")); |
sm.checkPermission(new RuntimePermission("getClassLoader")); |
813 |
{ |
{ |
814 |
synchronized (definedPackages) |
synchronized (definedPackages) |
815 |
{ |
{ |
816 |
p = (Package) definedPackages.get(name); |
p = definedPackages.get(name); |
817 |
} |
} |
818 |
} |
} |
819 |
return p; |
return p; |
903 |
{ |
{ |
904 |
if (packageAssertionStatus == null) |
if (packageAssertionStatus == null) |
905 |
packageAssertionStatus |
packageAssertionStatus |
906 |
= new HashMap(systemPackageAssertionStatus); |
= new HashMap<String, Boolean>(systemPackageAssertionStatus); |
907 |
packageAssertionStatus.put(name, Boolean.valueOf(enabled)); |
packageAssertionStatus.put(name, Boolean.valueOf(enabled)); |
908 |
} |
} |
909 |
|
|
923 |
boolean enabled) |
boolean enabled) |
924 |
{ |
{ |
925 |
if (classAssertionStatus == null) |
if (classAssertionStatus == null) |
926 |
classAssertionStatus = new HashMap(systemClassAssertionStatus); |
classAssertionStatus |
927 |
|
= new HashMap<String, Boolean>(systemClassAssertionStatus); |
928 |
// The toString() hack catches null, as required. |
// The toString() hack catches null, as required. |
929 |
classAssertionStatus.put(name.toString(), Boolean.valueOf(enabled)); |
classAssertionStatus.put(name.toString(), Boolean.valueOf(enabled)); |
930 |
} |
} |
942 |
public synchronized void clearAssertionStatus() |
public synchronized void clearAssertionStatus() |
943 |
{ |
{ |
944 |
defaultAssertionStatus = false; |
defaultAssertionStatus = false; |
945 |
packageAssertionStatus = new HashMap(); |
packageAssertionStatus = null; |
946 |
classAssertionStatus = new HashMap(); |
classAssertionStatus = null; |
947 |
} |
} |
948 |
|
|
949 |
/** |
/** |