1 | // ClassLoader.java - Define policies for loading Java classes.
|
---|
2 |
|
---|
3 | /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation
|
---|
4 |
|
---|
5 | This file is part of libgcj.
|
---|
6 |
|
---|
7 | This software is copyrighted work licensed under the terms of the
|
---|
8 | Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
---|
9 | details. */
|
---|
10 |
|
---|
11 | package java.lang;
|
---|
12 |
|
---|
13 | import java.io.InputStream;
|
---|
14 | import java.io.IOException;
|
---|
15 | import java.net.URL;
|
---|
16 | import java.security.AllPermission;
|
---|
17 | import java.security.CodeSource;
|
---|
18 | import java.security.Permission;
|
---|
19 | import java.security.Permissions;
|
---|
20 | import java.security.Policy;
|
---|
21 | import java.security.ProtectionDomain;
|
---|
22 | import java.util.*;
|
---|
23 |
|
---|
24 | /**
|
---|
25 | * The ClassLoader is a way of customizing the way Java gets its classes
|
---|
26 | * and loads them into memory. The verifier and other standard Java things
|
---|
27 | * still run, but the ClassLoader is allowed great flexibility in determining
|
---|
28 | * where to get the classfiles and when to load and resolve them. For that
|
---|
29 | * matter, a custom ClassLoader can perform on-the-fly code generation or
|
---|
30 | * modification!
|
---|
31 | *
|
---|
32 | * <p>Every classloader has a parent classloader that is consulted before
|
---|
33 | * the 'child' classloader when classes or resources should be loaded.
|
---|
34 | * This is done to make sure that classes can be loaded from an hierarchy of
|
---|
35 | * multiple classloaders and classloaders do not accidentially redefine
|
---|
36 | * already loaded classes by classloaders higher in the hierarchy.
|
---|
37 | *
|
---|
38 | * <p>The grandparent of all classloaders is the bootstrap classloader, which
|
---|
39 | * loads all the standard system classes as implemented by GNU Classpath. The
|
---|
40 | * other special classloader is the system classloader (also called
|
---|
41 | * application classloader) that loads all classes from the CLASSPATH
|
---|
42 | * (<code>java.class.path</code> system property). The system classloader
|
---|
43 | * is responsible for finding the application classes from the classpath,
|
---|
44 | * and delegates all requests for the standard library classes to its parent
|
---|
45 | * the bootstrap classloader. Most programs will load all their classes
|
---|
46 | * through the system classloaders.
|
---|
47 | *
|
---|
48 | * <p>The bootstrap classloader in GNU Classpath is implemented as a couple of
|
---|
49 | * static (native) methods on the package private class
|
---|
50 | * <code>java.lang.VMClassLoader</code>, the system classloader is an
|
---|
51 | * instance of <code>gnu.java.lang.SystemClassLoader</code>
|
---|
52 | * (which is a subclass of <code>java.net.URLClassLoader</code>).
|
---|
53 | *
|
---|
54 | * <p>Users of a <code>ClassLoader</code> will normally just use the methods
|
---|
55 | * <ul>
|
---|
56 | * <li> <code>loadClass()</code> to load a class.</li>
|
---|
57 | * <li> <code>getResource()</code> or <code>getResourceAsStream()</code>
|
---|
58 | * to access a resource.</li>
|
---|
59 | * <li> <code>getResources()</code> to get an Enumeration of URLs to all
|
---|
60 | * the resources provided by the classloader and its parents with the
|
---|
61 | * same name.</li>
|
---|
62 | * </ul>
|
---|
63 | *
|
---|
64 | * <p>Subclasses should implement the methods
|
---|
65 | * <ul>
|
---|
66 | * <li> <code>findClass()</code> which is called by <code>loadClass()</code>
|
---|
67 | * when the parent classloader cannot provide a named class.</li>
|
---|
68 | * <li> <code>findResource()</code> which is called by
|
---|
69 | * <code>getResource()</code> when the parent classloader cannot provide
|
---|
70 | * a named resource.</li>
|
---|
71 | * <li> <code>findResources()</code> which is called by
|
---|
72 | * <code>getResource()</code> to combine all the resources with the
|
---|
73 | * same name from the classloader and its parents.</li>
|
---|
74 | * <li> <code>findLibrary()</code> which is called by
|
---|
75 | * <code>Runtime.loadLibrary()</code> when a class defined by the
|
---|
76 | * classloader wants to load a native library.</li>
|
---|
77 | * </ul>
|
---|
78 | *
|
---|
79 | * @author John Keiser
|
---|
80 | * @author Mark Wielaard
|
---|
81 | * @author Eric Blake
|
---|
82 | * @author Kresten Krab Thorup
|
---|
83 | * @see Class
|
---|
84 | * @since 1.0
|
---|
85 | * @status still missing 1.4 functionality
|
---|
86 | */
|
---|
87 | public abstract class ClassLoader
|
---|
88 | {
|
---|
89 | /**
|
---|
90 | * All classes loaded by this classloader. VM's may choose to implement
|
---|
91 | * this cache natively; but it is here available for use if necessary. It
|
---|
92 | * is not private in order to allow native code (and trusted subclasses)
|
---|
93 | * access to this field.
|
---|
94 | */
|
---|
95 | final Map loadedClasses = new HashMap();
|
---|
96 |
|
---|
97 | /**
|
---|
98 | * The desired assertion status of classes loaded by this loader, if not
|
---|
99 | * overridden by package or class instructions.
|
---|
100 | */
|
---|
101 | // Package visible for use by Class.
|
---|
102 | boolean defaultAssertionStatus = VMClassLoader.defaultAssertionStatus();
|
---|
103 |
|
---|
104 | /**
|
---|
105 | * The command-line state of the package assertion status overrides. This
|
---|
106 | * map is never modified, so it does not need to be synchronized.
|
---|
107 | */
|
---|
108 | // Package visible for use by Class.
|
---|
109 | static final Map systemPackageAssertionStatus
|
---|
110 | = VMClassLoader.packageAssertionStatus();
|
---|
111 |
|
---|
112 | /**
|
---|
113 | * The map of package assertion status overrides, or null if no package
|
---|
114 | * overrides have been specified yet. The values of the map should be
|
---|
115 | * Boolean.TRUE or Boolean.FALSE, and the unnamed package is represented
|
---|
116 | * by the null key. This map must be synchronized on this instance.
|
---|
117 | */
|
---|
118 | // Package visible for use by Class.
|
---|
119 | Map packageAssertionStatus;
|
---|
120 |
|
---|
121 | /**
|
---|
122 | * The command-line state of the class assertion status overrides. This
|
---|
123 | * map is never modified, so it does not need to be synchronized.
|
---|
124 | */
|
---|
125 | // Package visible for use by Class.
|
---|
126 | static final Map systemClassAssertionStatus
|
---|
127 | = VMClassLoader.classAssertionStatus();
|
---|
128 |
|
---|
129 | /**
|
---|
130 | * The map of class assertion status overrides, or null if no class
|
---|
131 | * overrides have been specified yet. The values of the map should be
|
---|
132 | * Boolean.TRUE or Boolean.FALSE. This map must be synchronized on this
|
---|
133 | * instance.
|
---|
134 | */
|
---|
135 | // Package visible for use by Class.
|
---|
136 | Map classAssertionStatus;
|
---|
137 |
|
---|
138 | /**
|
---|
139 | * The classloader that is consulted before this classloader.
|
---|
140 | * If null then the parent is the bootstrap classloader.
|
---|
141 | */
|
---|
142 | private final ClassLoader parent;
|
---|
143 |
|
---|
144 | /**
|
---|
145 | * All packages defined by this classloader. It is not private in order to
|
---|
146 | * allow native code (and trusted subclasses) access to this field.
|
---|
147 | */
|
---|
148 | private HashMap definedPackages = new HashMap();
|
---|
149 |
|
---|
150 | /**
|
---|
151 | * Returns the parent of this classloader. If the parent of this
|
---|
152 | * classloader is the bootstrap classloader then this method returns
|
---|
153 | * <code>null</code>. A security check may be performed on
|
---|
154 | * <code>RuntimePermission("getClassLoader")</code>.
|
---|
155 | *
|
---|
156 | * @throws SecurityException if the security check fails
|
---|
157 | * @since 1.2
|
---|
158 | */
|
---|
159 | public final ClassLoader getParent ()
|
---|
160 | {
|
---|
161 | // Check if we may return the parent classloader
|
---|
162 | SecurityManager sm = System.getSecurityManager();
|
---|
163 | if (sm != null)
|
---|
164 | {
|
---|
165 | /* FIXME: security, getClassContext() not implemented.
|
---|
166 | Class c = VMSecurityManager.getClassContext()[1];
|
---|
167 | ClassLoader cl = c.getClassLoader();
|
---|
168 | if (cl != null && cl != this)
|
---|
169 | sm.checkPermission(new RuntimePermission("getClassLoader"));
|
---|
170 | */
|
---|
171 | }
|
---|
172 | return parent;
|
---|
173 | }
|
---|
174 |
|
---|
175 | /**
|
---|
176 | * Returns the system classloader. The system classloader (also called
|
---|
177 | * the application classloader) is the classloader that was used to
|
---|
178 | * load the application classes on the classpath (given by the system
|
---|
179 | * property <code>java.class.path</code>. This is set as the context
|
---|
180 | * class loader for a thread. The system property
|
---|
181 | * <code>java.system.class.loader</code>, if defined, is taken to be the
|
---|
182 | * name of the class to use as the system class loader, which must have
|
---|
183 | * a public constructor which takes a ClassLoader as a parent; otherwise this
|
---|
184 | * uses gnu.java.lang.SystemClassLoader.
|
---|
185 | *
|
---|
186 | * <p>Note that this is different from the bootstrap classloader that
|
---|
187 | * actually loads all the real "system" classes (the bootstrap classloader
|
---|
188 | * is the parent of the returned system classloader).
|
---|
189 | *
|
---|
190 | * <p>A security check will be performed for
|
---|
191 | * <code>RuntimePermission("getClassLoader")</code> if the calling class
|
---|
192 | * is not a parent of the system class loader.
|
---|
193 | *
|
---|
194 | * @return the system class loader
|
---|
195 | * @throws SecurityException if the security check fails
|
---|
196 | * @throws IllegalStateException if this is called recursively
|
---|
197 | * @throws Error if <code>java.system.class.loader</code> fails to load
|
---|
198 | * @since 1.2
|
---|
199 | */
|
---|
200 | public static ClassLoader getSystemClassLoader ()
|
---|
201 | {
|
---|
202 | return gnu.gcj.runtime.VMClassLoader.instance;
|
---|
203 | }
|
---|
204 |
|
---|
205 | /**
|
---|
206 | * Creates a <code>ClassLoader</code> with no parent.
|
---|
207 | * @exception java.lang.SecurityException if not allowed
|
---|
208 | */
|
---|
209 | protected ClassLoader()
|
---|
210 | {
|
---|
211 | this (null);
|
---|
212 | }
|
---|
213 |
|
---|
214 | /**
|
---|
215 | * Creates a <code>ClassLoader</code> with the given parent.
|
---|
216 | * The parent may be <code>null</code>.
|
---|
217 | * The only thing this
|
---|
218 | * constructor does, is to call
|
---|
219 | * <code>checkCreateClassLoader</code> on the current
|
---|
220 | * security manager.
|
---|
221 | * @exception java.lang.SecurityException if not allowed
|
---|
222 | * @since 1.2
|
---|
223 | */
|
---|
224 | protected ClassLoader(ClassLoader parent)
|
---|
225 | {
|
---|
226 | SecurityManager security = System.getSecurityManager ();
|
---|
227 | if (security != null)
|
---|
228 | security.checkCreateClassLoader ();
|
---|
229 | this.parent = parent;
|
---|
230 | }
|
---|
231 |
|
---|
232 | /**
|
---|
233 | * Loads and link the class by the given name.
|
---|
234 | * @param name the name of the class.
|
---|
235 | * @return the class loaded.
|
---|
236 | * @see ClassLoader#loadClass(String,boolean)
|
---|
237 | * @exception java.lang.ClassNotFoundException
|
---|
238 | */
|
---|
239 | public Class loadClass(String name)
|
---|
240 | throws java.lang.ClassNotFoundException
|
---|
241 | {
|
---|
242 | return loadClass (name, false);
|
---|
243 | }
|
---|
244 |
|
---|
245 | /**
|
---|
246 | * Loads the class by the given name. The default implementation
|
---|
247 | * will search for the class in the following order (similar to jdk 1.2)
|
---|
248 | * <ul>
|
---|
249 | * <li> First <code>findLoadedClass</code>.
|
---|
250 | * <li> If parent is non-null, <code>parent.loadClass</code>;
|
---|
251 | * otherwise <code>findSystemClass</code>.
|
---|
252 | * <li> <code>findClass</code>.
|
---|
253 | * </ul>
|
---|
254 | * If <code>link</code> is true, <code>resolveClass</code> is then
|
---|
255 | * called. <p> Normally, this need not be overridden; override
|
---|
256 | * <code>findClass</code> instead.
|
---|
257 | * @param name the name of the class.
|
---|
258 | * @param link if the class should be linked.
|
---|
259 | * @return the class loaded.
|
---|
260 | * @exception java.lang.ClassNotFoundException
|
---|
261 | * @deprecated
|
---|
262 | */
|
---|
263 | protected Class loadClass(String name, boolean link)
|
---|
264 | throws java.lang.ClassNotFoundException
|
---|
265 | {
|
---|
266 | Class c = findLoadedClass (name);
|
---|
267 |
|
---|
268 | if (c == null)
|
---|
269 | {
|
---|
270 | try
|
---|
271 | {
|
---|
272 | ClassLoader cl = parent;
|
---|
273 | if (parent == null)
|
---|
274 | cl = gnu.gcj.runtime.VMClassLoader.instance;
|
---|
275 | if (cl != this)
|
---|
276 | c = cl.loadClass (name, link);
|
---|
277 | }
|
---|
278 | catch (ClassNotFoundException ex)
|
---|
279 | {
|
---|
280 | /* ignore, we'll try findClass */;
|
---|
281 | }
|
---|
282 | }
|
---|
283 |
|
---|
284 | if (c == null)
|
---|
285 | c = findClass (name);
|
---|
286 |
|
---|
287 | if (c == null)
|
---|
288 | throw new ClassNotFoundException (name);
|
---|
289 |
|
---|
290 | if (link)
|
---|
291 | resolveClass (c);
|
---|
292 |
|
---|
293 | return c;
|
---|
294 | }
|
---|
295 |
|
---|
296 | /**
|
---|
297 | * Called for every class name that is needed but has not yet been
|
---|
298 | * defined by this classloader or one of its parents. It is called by
|
---|
299 | * <code>loadClass()</code> after both <code>findLoadedClass()</code> and
|
---|
300 | * <code>parent.loadClass()</code> couldn't provide the requested class.
|
---|
301 | *
|
---|
302 | * <p>The default implementation throws a
|
---|
303 | * <code>ClassNotFoundException</code>. Subclasses should override this
|
---|
304 | * method. An implementation of this method in a subclass should get the
|
---|
305 | * class bytes of the class (if it can find them), if the package of the
|
---|
306 | * requested class doesn't exist it should define the package and finally
|
---|
307 | * it should call define the actual class. It does not have to resolve the
|
---|
308 | * class. It should look something like the following:<br>
|
---|
309 | *
|
---|
310 | * <pre>
|
---|
311 | * // Get the bytes that describe the requested class
|
---|
312 | * byte[] classBytes = classLoaderSpecificWayToFindClassBytes(name);
|
---|
313 | * // Get the package name
|
---|
314 | * int lastDot = name.lastIndexOf('.');
|
---|
315 | * if (lastDot != -1)
|
---|
316 | * {
|
---|
317 | * String packageName = name.substring(0, lastDot);
|
---|
318 | * // Look if the package already exists
|
---|
319 | * if (getPackage(pkg) == null)
|
---|
320 | * {
|
---|
321 | * // define the package
|
---|
322 | * definePackage(packageName, ...);
|
---|
323 | * }
|
---|
324 | * }
|
---|
325 | * // Define and return the class
|
---|
326 | * return defineClass(name, classBytes, 0, classBytes.length);
|
---|
327 | * </pre>
|
---|
328 | *
|
---|
329 | * <p><code>loadClass()</code> makes sure that the <code>Class</code>
|
---|
330 | * returned by <code>findClass()</code> will later be returned by
|
---|
331 | * <code>findLoadedClass()</code> when the same class name is requested.
|
---|
332 | *
|
---|
333 | * @param name class name to find (including the package name)
|
---|
334 | * @return the requested Class
|
---|
335 | * @throws ClassNotFoundException when the class can not be found
|
---|
336 | * @since 1.2
|
---|
337 | */
|
---|
338 | protected Class findClass (String name)
|
---|
339 | throws ClassNotFoundException
|
---|
340 | {
|
---|
341 | throw new ClassNotFoundException (name);
|
---|
342 | }
|
---|
343 |
|
---|
344 | // Protection Domain definitions
|
---|
345 | // FIXME: should there be a special protection domain used for native code?
|
---|
346 |
|
---|
347 | // The permission required to check what a classes protection domain is.
|
---|
348 | static final Permission protectionDomainPermission
|
---|
349 | = new RuntimePermission("getProtectionDomain");
|
---|
350 | // The protection domain returned if we cannot determine it.
|
---|
351 | static ProtectionDomain unknownProtectionDomain;
|
---|
352 | // Protection domain to use when a class is defined without one specified.
|
---|
353 | static ProtectionDomain defaultProtectionDomain;
|
---|
354 |
|
---|
355 | static
|
---|
356 | {
|
---|
357 | Permissions permissions = new Permissions();
|
---|
358 | permissions.add(new AllPermission());
|
---|
359 | unknownProtectionDomain = new ProtectionDomain(null, permissions);
|
---|
360 |
|
---|
361 | CodeSource cs = new CodeSource(null, null);
|
---|
362 | defaultProtectionDomain =
|
---|
363 | new ProtectionDomain(cs, Policy.getPolicy().getPermissions(cs));
|
---|
364 | }
|
---|
365 |
|
---|
366 | /**
|
---|
367 | * Defines a class, given the class-data. According to the JVM, this
|
---|
368 | * method should not be used; instead use the variant of this method
|
---|
369 | * in which the name of the class being defined is specified
|
---|
370 | * explicitly.
|
---|
371 | * <P>
|
---|
372 | * If the name of the class, as specified (implicitly) in the class
|
---|
373 | * data, denotes a class which has already been loaded by this class
|
---|
374 | * loader, an instance of
|
---|
375 | * <code>java.lang.ClassNotFoundException</code> will be thrown.
|
---|
376 | *
|
---|
377 | * @param data bytes in class file format.
|
---|
378 | * @param off offset to start interpreting data.
|
---|
379 | * @param len length of data in class file.
|
---|
380 | * @return the class defined.
|
---|
381 | * @exception java.lang.ClassNotFoundException
|
---|
382 | * @exception java.lang.LinkageError
|
---|
383 | * @see ClassLoader#defineClass(String,byte[],int,int) */
|
---|
384 | protected final Class defineClass(byte[] data, int off, int len)
|
---|
385 | throws ClassFormatError
|
---|
386 | {
|
---|
387 | return defineClass (null, data, off, len, defaultProtectionDomain);
|
---|
388 | }
|
---|
389 |
|
---|
390 | /**
|
---|
391 | * Helper to define a class using a string of bytes without a
|
---|
392 | * ProtectionDomain. Subclasses should call this method from their
|
---|
393 | * <code>findClass()</code> implementation. The name should use '.'
|
---|
394 | * separators, and discard the trailing ".class". The default protection
|
---|
395 | * domain has the permissions of
|
---|
396 | * <code>Policy.getPolicy().getPermissions(new CodeSource(null, null))<code>.
|
---|
397 | *
|
---|
398 | * @param name the name to give the class, or null if unknown
|
---|
399 | * @param data the data representing the classfile, in classfile format
|
---|
400 | * @param offset the offset into the data where the classfile starts
|
---|
401 | * @param len the length of the classfile data in the array
|
---|
402 | * @return the class that was defined
|
---|
403 | * @throws ClassFormatError if data is not in proper classfile format
|
---|
404 | * @throws IndexOutOfBoundsException if offset or len is negative, or
|
---|
405 | * offset + len exceeds data
|
---|
406 | * @throws SecurityException if name starts with "java."
|
---|
407 | * @since 1.1
|
---|
408 | */
|
---|
409 | protected final Class defineClass(String name, byte[] data, int off, int len)
|
---|
410 | throws ClassFormatError
|
---|
411 | {
|
---|
412 | return defineClass (name, data, off, len, defaultProtectionDomain);
|
---|
413 | }
|
---|
414 |
|
---|
415 | /**
|
---|
416 | * Defines a class, given the class-data. This is preferable
|
---|
417 | * over <code>defineClass(byte[],off,len)</code> since it is more
|
---|
418 | * secure. If the expected name does not match that of the class
|
---|
419 | * file, <code>ClassNotFoundException</code> is thrown. If
|
---|
420 | * <code>name</code> denotes the name of an already loaded class, a
|
---|
421 | * <code>LinkageError</code> is thrown.
|
---|
422 | * <p>
|
---|
423 | *
|
---|
424 | * FIXME: How do we assure that the class-file data is not being
|
---|
425 | * modified, simultaneously with the class loader running!? If this
|
---|
426 | * was done in some very clever way, it might break security.
|
---|
427 | * Right now I am thinking that defineclass should make sure never to
|
---|
428 | * read an element of this array more than once, and that that would
|
---|
429 | * assure the ``immutable'' appearance. It is still to be determined
|
---|
430 | * if this is in fact how defineClass operates.
|
---|
431 | *
|
---|
432 | * @param name the expected name.
|
---|
433 | * @param data bytes in class file format.
|
---|
434 | * @param off offset to start interpreting data.
|
---|
435 | * @param len length of data in class file.
|
---|
436 | * @param protectionDomain security protection domain for the class.
|
---|
437 | * @return the class defined.
|
---|
438 | * @exception java.lang.ClassNotFoundException
|
---|
439 | * @exception java.lang.LinkageError
|
---|
440 | */
|
---|
441 | protected final synchronized Class defineClass(String name,
|
---|
442 | byte[] data,
|
---|
443 | int off,
|
---|
444 | int len,
|
---|
445 | ProtectionDomain protectionDomain)
|
---|
446 | throws ClassFormatError
|
---|
447 | {
|
---|
448 | if (data==null || data.length < off+len || off<0 || len<0)
|
---|
449 | throw new ClassFormatError ("arguments to defineClass "
|
---|
450 | + "are meaningless");
|
---|
451 |
|
---|
452 | // as per 5.3.5.1
|
---|
453 | if (name != null && findLoadedClass (name) != null)
|
---|
454 | throw new java.lang.LinkageError ("class "
|
---|
455 | + name
|
---|
456 | + " already loaded");
|
---|
457 |
|
---|
458 | if (protectionDomain == null)
|
---|
459 | protectionDomain = defaultProtectionDomain;
|
---|
460 |
|
---|
461 | try
|
---|
462 | {
|
---|
463 | Class retval = defineClass0 (name, data, off, len, protectionDomain);
|
---|
464 | loadedClasses.put(retval.getName(), retval);
|
---|
465 | return retval;
|
---|
466 | }
|
---|
467 | catch (LinkageError x)
|
---|
468 | {
|
---|
469 | throw x; // rethrow
|
---|
470 | }
|
---|
471 | catch (VirtualMachineError x)
|
---|
472 | {
|
---|
473 | throw x; // rethrow
|
---|
474 | }
|
---|
475 | catch (Throwable x)
|
---|
476 | {
|
---|
477 | // This should never happen, or we are beyond spec.
|
---|
478 | InternalError r = new InternalError ("Unexpected exception "
|
---|
479 | + "while defining class "
|
---|
480 | + name);
|
---|
481 | r.initCause(x);
|
---|
482 | throw r;
|
---|
483 | }
|
---|
484 | }
|
---|
485 |
|
---|
486 | /** This is the entry point of defineClass into the native code */
|
---|
487 | private native Class defineClass0 (String name,
|
---|
488 | byte[] data,
|
---|
489 | int off,
|
---|
490 | int len,
|
---|
491 | ProtectionDomain protectionDomain)
|
---|
492 | throws ClassFormatError;
|
---|
493 |
|
---|
494 | /**
|
---|
495 | * Link the given class. This will bring the class to a state where
|
---|
496 | * the class initializer can be run. Linking involves the following
|
---|
497 | * steps:
|
---|
498 | * <UL>
|
---|
499 | * <LI> Prepare (allocate and internalize) the constant strings that
|
---|
500 | * are used in this class.
|
---|
501 | * <LI> Allocate storage for static fields, and define the layout
|
---|
502 | * of instance fields.
|
---|
503 | * <LI> Perform static initialization of ``static final'' int,
|
---|
504 | * long, float, double and String fields for which there is a
|
---|
505 | * compile-time constant initializer.
|
---|
506 | * <LI> Create the internal representation of the ``vtable''.
|
---|
507 | * </UL>
|
---|
508 | * For <code>gcj</code>-compiled classes, only the first step is
|
---|
509 | * performed. The compiler will have done the rest already.
|
---|
510 | * <P>
|
---|
511 | * This is called by the system automatically,
|
---|
512 | * as part of class initialization; there is no reason to ever call
|
---|
513 | * this method directly.
|
---|
514 | * <P>
|
---|
515 | * For historical reasons, this method has a name which is easily
|
---|
516 | * misunderstood. Java classes are never ``resolved''. Classes are
|
---|
517 | * linked; whereas method and field references are resolved.
|
---|
518 | *
|
---|
519 | * @param clazz the class to link.
|
---|
520 | * @exception java.lang.LinkageError
|
---|
521 | */
|
---|
522 | protected final void resolveClass(Class clazz)
|
---|
523 | {
|
---|
524 | resolveClass0(clazz);
|
---|
525 | }
|
---|
526 |
|
---|
527 | static void resolveClass0(Class clazz)
|
---|
528 | {
|
---|
529 | synchronized (clazz)
|
---|
530 | {
|
---|
531 | try
|
---|
532 | {
|
---|
533 | linkClass0 (clazz);
|
---|
534 | }
|
---|
535 | catch (Throwable x)
|
---|
536 | {
|
---|
537 | markClassErrorState0 (clazz);
|
---|
538 |
|
---|
539 | LinkageError e;
|
---|
540 | if (x instanceof LinkageError)
|
---|
541 | e = (LinkageError)x;
|
---|
542 | else if (x instanceof ClassNotFoundException)
|
---|
543 | {
|
---|
544 | e = new NoClassDefFoundError("while resolving class: "
|
---|
545 | + clazz.getName());
|
---|
546 | e.initCause (x);
|
---|
547 | }
|
---|
548 | else
|
---|
549 | {
|
---|
550 | e = new LinkageError ("unexpected exception during linking: "
|
---|
551 | + clazz.getName());
|
---|
552 | e.initCause (x);
|
---|
553 | }
|
---|
554 | throw e;
|
---|
555 | }
|
---|
556 | }
|
---|
557 | }
|
---|
558 |
|
---|
559 | /** Internal method. Calls _Jv_PrepareClass and
|
---|
560 | * _Jv_PrepareCompiledClass. This is only called from resolveClass. */
|
---|
561 | private static native void linkClass0(Class clazz);
|
---|
562 |
|
---|
563 | /** Internal method. Marks the given clazz to be in an erroneous
|
---|
564 | * state, and calls notifyAll() on the class object. This should only
|
---|
565 | * be called when the caller has the lock on the class object. */
|
---|
566 | private static native void markClassErrorState0(Class clazz);
|
---|
567 |
|
---|
568 | /**
|
---|
569 | * Defines a new package and creates a Package object.
|
---|
570 | * The package should be defined before any class in the package is
|
---|
571 | * defined with <code>defineClass()</code>. The package should not yet
|
---|
572 | * be defined before in this classloader or in one of its parents (which
|
---|
573 | * means that <code>getPackage()</code> should return <code>null</code>).
|
---|
574 | * All parameters except the <code>name</code> of the package may be
|
---|
575 | * <code>null</code>.
|
---|
576 | * <p>
|
---|
577 | * Subclasses should call this method from their <code>findClass()</code>
|
---|
578 | * implementation before calling <code>defineClass()</code> on a Class
|
---|
579 | * in a not yet defined Package (which can be checked by calling
|
---|
580 | * <code>getPackage()</code>).
|
---|
581 | *
|
---|
582 | * @param name The name of the Package
|
---|
583 | * @param specTitle The name of the specification
|
---|
584 | * @param specVendor The name of the specification designer
|
---|
585 | * @param specVersion The version of this specification
|
---|
586 | * @param implTitle The name of the implementation
|
---|
587 | * @param implVendor The vendor that wrote this implementation
|
---|
588 | * @param implVersion The version of this implementation
|
---|
589 | * @param sealed If sealed the origin of the package classes
|
---|
590 | * @return the Package object for the specified package
|
---|
591 | *
|
---|
592 | * @exception IllegalArgumentException if the package name is null or if
|
---|
593 | * it was already defined by this classloader or one of its parents.
|
---|
594 | *
|
---|
595 | * @see Package
|
---|
596 | * @since 1.2
|
---|
597 | */
|
---|
598 | protected Package definePackage(String name,
|
---|
599 | String specTitle, String specVendor,
|
---|
600 | String specVersion, String implTitle,
|
---|
601 | String implVendor, String implVersion,
|
---|
602 | URL sealed)
|
---|
603 | {
|
---|
604 | if (getPackage(name) != null)
|
---|
605 | throw new IllegalArgumentException("Package " + name
|
---|
606 | + " already defined");
|
---|
607 | Package p = new Package(name,
|
---|
608 | specTitle, specVendor, specVersion,
|
---|
609 | implTitle, implVendor, implVersion,
|
---|
610 | sealed);
|
---|
611 | synchronized (definedPackages)
|
---|
612 | {
|
---|
613 | definedPackages.put(name, p);
|
---|
614 | }
|
---|
615 | return p;
|
---|
616 | }
|
---|
617 |
|
---|
618 | /**
|
---|
619 | * Returns the Package object for the requested package name. It returns
|
---|
620 | * null when the package is not defined by this classloader or one of its
|
---|
621 | * parents.
|
---|
622 | *
|
---|
623 | * @param name the package name to find
|
---|
624 | * @return the package, if defined
|
---|
625 | * @since 1.2
|
---|
626 | */
|
---|
627 | protected Package getPackage(String name)
|
---|
628 | {
|
---|
629 | Package p;
|
---|
630 | if (parent == null)
|
---|
631 | // XXX - Should we use the bootstrap classloader?
|
---|
632 | p = null;
|
---|
633 | else
|
---|
634 | p = parent.getPackage(name);
|
---|
635 |
|
---|
636 | if (p == null)
|
---|
637 | {
|
---|
638 | synchronized (definedPackages)
|
---|
639 | {
|
---|
640 | p = (Package) definedPackages.get(name);
|
---|
641 | }
|
---|
642 | }
|
---|
643 |
|
---|
644 | return p;
|
---|
645 | }
|
---|
646 |
|
---|
647 | /**
|
---|
648 | * Returns all Package objects defined by this classloader and its parents.
|
---|
649 | *
|
---|
650 | * @return an array of all defined packages
|
---|
651 | * @since 1.2
|
---|
652 | */
|
---|
653 | protected Package[] getPackages()
|
---|
654 | {
|
---|
655 | Package[] allPackages;
|
---|
656 |
|
---|
657 | // Get all our packages.
|
---|
658 | Package[] packages;
|
---|
659 | synchronized(definedPackages)
|
---|
660 | {
|
---|
661 | packages = new Package[definedPackages.size()];
|
---|
662 | definedPackages.values().toArray(packages);
|
---|
663 | }
|
---|
664 |
|
---|
665 | // If we have a parent get all packages defined by our parents.
|
---|
666 | if (parent != null)
|
---|
667 | {
|
---|
668 | Package[] parentPackages = parent.getPackages();
|
---|
669 | allPackages = new Package[parentPackages.length + packages.length];
|
---|
670 | System.arraycopy(parentPackages, 0, allPackages, 0,
|
---|
671 | parentPackages.length);
|
---|
672 | System.arraycopy(packages, 0, allPackages, parentPackages.length,
|
---|
673 | packages.length);
|
---|
674 | }
|
---|
675 | else
|
---|
676 | // XXX - Should we use the bootstrap classloader?
|
---|
677 | allPackages = packages;
|
---|
678 |
|
---|
679 | return allPackages;
|
---|
680 | }
|
---|
681 |
|
---|
682 | /**
|
---|
683 | * Called by <code>Runtime.loadLibrary()</code> to get an absolute path
|
---|
684 | * to a (system specific) library that was requested by a class loaded
|
---|
685 | * by this classloader. The default implementation returns
|
---|
686 | * <code>null</code>. It should be implemented by subclasses when they
|
---|
687 | * have a way to find the absolute path to a library. If this method
|
---|
688 | * returns null the library is searched for in the default locations
|
---|
689 | * (the directories listed in the <code>java.library.path</code> system
|
---|
690 | * property).
|
---|
691 | *
|
---|
692 | * @param name the (system specific) name of the requested library
|
---|
693 | * @return the full pathname to the requested library, or null
|
---|
694 | * @see Runtime#loadLibrary()
|
---|
695 | * @since 1.2
|
---|
696 | */
|
---|
697 | protected String findLibrary(String name)
|
---|
698 | {
|
---|
699 | return null;
|
---|
700 | }
|
---|
701 |
|
---|
702 | /**
|
---|
703 | * Returns a class found in a system-specific way, typically
|
---|
704 | * via the <code>java.class.path</code> system property. Loads the
|
---|
705 | * class if necessary.
|
---|
706 | *
|
---|
707 | * @param name the class to resolve.
|
---|
708 | * @return the class loaded.
|
---|
709 | * @exception java.lang.LinkageError
|
---|
710 | * @exception java.lang.ClassNotFoundException
|
---|
711 | */
|
---|
712 | protected final Class findSystemClass(String name)
|
---|
713 | throws java.lang.ClassNotFoundException
|
---|
714 | {
|
---|
715 | return gnu.gcj.runtime.VMClassLoader.instance.loadClass (name);
|
---|
716 | }
|
---|
717 |
|
---|
718 | /**
|
---|
719 | * Helper to set the signers of a class. This should be called after
|
---|
720 | * defining the class.
|
---|
721 | *
|
---|
722 | * @param c the Class to set signers of
|
---|
723 | * @param signers the signers to set
|
---|
724 | * @since 1.1
|
---|
725 | */
|
---|
726 | protected final void setSigners(Class c, Object[] signers)
|
---|
727 | {
|
---|
728 | /*
|
---|
729 | * Does currently nothing. FIXME.
|
---|
730 | */
|
---|
731 | }
|
---|
732 |
|
---|
733 | /**
|
---|
734 | * If a class named <code>name</code> was previously loaded using
|
---|
735 | * this <code>ClassLoader</code>, then it is returned. Otherwise
|
---|
736 | * it returns <code>null</code>.
|
---|
737 | * @param name class to find.
|
---|
738 | * @return the class loaded, or null.
|
---|
739 | */
|
---|
740 | protected final synchronized Class findLoadedClass(String name)
|
---|
741 | {
|
---|
742 | return (Class) loadedClasses.get(name);
|
---|
743 | }
|
---|
744 |
|
---|
745 | /**
|
---|
746 | * Get a resource using the system classloader.
|
---|
747 | *
|
---|
748 | * @param name the name of the resource relative to the system classloader
|
---|
749 | * @return an input stream for the resource, or null
|
---|
750 | * @since 1.1
|
---|
751 | */
|
---|
752 | public static InputStream getSystemResourceAsStream(String name) {
|
---|
753 | return getSystemClassLoader().getResourceAsStream (name);
|
---|
754 | }
|
---|
755 |
|
---|
756 | /**
|
---|
757 | * Get the URL to a resource using the system classloader.
|
---|
758 | *
|
---|
759 | * @param name the name of the resource relative to the system classloader
|
---|
760 | * @return the URL to the resource
|
---|
761 | * @since 1.1
|
---|
762 | */
|
---|
763 | public static URL getSystemResource(String name) {
|
---|
764 | return getSystemClassLoader().getResource (name);
|
---|
765 | }
|
---|
766 |
|
---|
767 | /**
|
---|
768 | * Get an Enumeration of URLs to resources with a given name using the
|
---|
769 | * the system classloader. The enumeration firsts lists the resources with
|
---|
770 | * the given name that can be found by the bootstrap classloader followed
|
---|
771 | * by the resources with the given name that can be found on the classpath.
|
---|
772 | *
|
---|
773 | * @param name the name of the resource relative to the system classloader
|
---|
774 | * @return an Enumeration of URLs to the resources
|
---|
775 | * @throws IOException if I/O errors occur in the process
|
---|
776 | * @since 1.2
|
---|
777 | */
|
---|
778 | public static Enumeration getSystemResources(String name) throws IOException
|
---|
779 | {
|
---|
780 | return getSystemClassLoader().getResources(name);
|
---|
781 | }
|
---|
782 |
|
---|
783 | /**
|
---|
784 | * Return an InputStream representing the resource name.
|
---|
785 | * This is essentially like
|
---|
786 | * <code>getResource(name).openStream()</code>, except
|
---|
787 | * it masks out any IOException and returns null on failure.
|
---|
788 | * @param name resource to load
|
---|
789 | * @return an InputStream, or null
|
---|
790 | * @see java.lang.ClassLoader#getResource(String)
|
---|
791 | * @see java.io.InputStream
|
---|
792 | */
|
---|
793 | public InputStream getResourceAsStream(String name)
|
---|
794 | {
|
---|
795 | try
|
---|
796 | {
|
---|
797 | URL res = getResource (name);
|
---|
798 | if (res == null)
|
---|
799 | return null;
|
---|
800 | return res.openStream ();
|
---|
801 | }
|
---|
802 | catch (java.io.IOException x)
|
---|
803 | {
|
---|
804 | return null;
|
---|
805 | }
|
---|
806 | }
|
---|
807 |
|
---|
808 | /**
|
---|
809 | * Return an java.io.URL representing the resouce <code>name</code>.
|
---|
810 | * The default implementation just returns <code>null</code>.
|
---|
811 | * @param name resource to load
|
---|
812 | * @return a URL, or null if there is no such resource.
|
---|
813 | * @see java.lang.ClassLoader#getResourceAsBytes(String)
|
---|
814 | * @see java.lang.ClassLoader#getResourceAsStream(String)
|
---|
815 | * @see java.io.URL
|
---|
816 | */
|
---|
817 | public URL getResource (String name)
|
---|
818 | {
|
---|
819 | // The rules say search the parent class if non-null,
|
---|
820 | // otherwise search the built-in class loader (assumed to be
|
---|
821 | // the system ClassLoader). If not found, call
|
---|
822 | // findResource().
|
---|
823 | URL result = null;
|
---|
824 |
|
---|
825 | ClassLoader delegate = parent;
|
---|
826 |
|
---|
827 | if (delegate == null)
|
---|
828 | delegate = getSystemClassLoader ();
|
---|
829 |
|
---|
830 | // Protect ourselves from looping.
|
---|
831 | if (this != delegate)
|
---|
832 | result = delegate.getResource (name);
|
---|
833 |
|
---|
834 | if (result != null)
|
---|
835 | return result;
|
---|
836 | else
|
---|
837 | return findResource (name);
|
---|
838 | }
|
---|
839 |
|
---|
840 | /**
|
---|
841 | * Called whenever a resource is needed that could not be provided by
|
---|
842 | * one of the parents of this classloader. It is called by
|
---|
843 | * <code>getResource()</code> after <code>parent.getResource()</code>
|
---|
844 | * couldn't provide the requested resource.
|
---|
845 | *
|
---|
846 | * <p>The default implementation always returns null. Subclasses should
|
---|
847 | * override this method when they can provide a way to return a URL
|
---|
848 | * to a named resource.
|
---|
849 | *
|
---|
850 | * @param name the name of the resource to be found
|
---|
851 | * @return a URL to the named resource or null when not found
|
---|
852 | * @since 1.2
|
---|
853 | */
|
---|
854 | protected URL findResource (String name)
|
---|
855 | {
|
---|
856 | // Default to returning null. Derived classes implement this.
|
---|
857 | return null;
|
---|
858 | }
|
---|
859 |
|
---|
860 | /**
|
---|
861 | * Returns an Enumeration of all resources with a given name that can
|
---|
862 | * be found by this classloader and its parents. Certain classloaders
|
---|
863 | * (such as the URLClassLoader when given multiple jar files) can have
|
---|
864 | * multiple resources with the same name that come from multiple locations.
|
---|
865 | * It can also occur that a parent classloader offers a resource with a
|
---|
866 | * certain name and the child classloader also offers a resource with that
|
---|
867 | * same name. <code>getResource() only offers the first resource (of the
|
---|
868 | * parent) with a given name. This method lists all resources with the
|
---|
869 | * same name. The name should use '/' as path separators.
|
---|
870 | *
|
---|
871 | * <p>The Enumeration is created by first calling <code>getResources()</code>
|
---|
872 | * on the parent classloader and then calling <code>findResources()</code>
|
---|
873 | * on this classloader.
|
---|
874 | *
|
---|
875 | * @param name the resource name
|
---|
876 | * @return an enumaration of all resources found
|
---|
877 | * @throws IOException if I/O errors occur in the process
|
---|
878 | * @since 1.2
|
---|
879 | */
|
---|
880 | public final Enumeration getResources(String name) throws IOException
|
---|
881 | {
|
---|
882 | // The rules say search the parent class if non-null,
|
---|
883 | // otherwise search the built-in class loader (assumed to be
|
---|
884 | // the system ClassLoader). If not found, call
|
---|
885 | // findResource().
|
---|
886 | Enumeration result = null;
|
---|
887 |
|
---|
888 | ClassLoader delegate = parent;
|
---|
889 |
|
---|
890 | if (delegate == null)
|
---|
891 | delegate = getSystemClassLoader ();
|
---|
892 |
|
---|
893 | // Protect ourselves from looping.
|
---|
894 | if (this != delegate)
|
---|
895 | result = delegate.getResources (name);
|
---|
896 |
|
---|
897 | if (result != null)
|
---|
898 | return result;
|
---|
899 | else
|
---|
900 | return findResources (name);
|
---|
901 | }
|
---|
902 |
|
---|
903 | /**
|
---|
904 | * Called whenever all locations of a named resource are needed.
|
---|
905 | * It is called by <code>getResources()</code> after it has called
|
---|
906 | * <code>parent.getResources()</code>. The results are combined by
|
---|
907 | * the <code>getResources()</code> method.
|
---|
908 | *
|
---|
909 | * <p>The default implementation always returns an empty Enumeration.
|
---|
910 | * Subclasses should override it when they can provide an Enumeration of
|
---|
911 | * URLs (possibly just one element) to the named resource.
|
---|
912 | * The first URL of the Enumeration should be the same as the one
|
---|
913 | * returned by <code>findResource</code>.
|
---|
914 | *
|
---|
915 | * @param name the name of the resource to be found
|
---|
916 | * @return a possibly empty Enumeration of URLs to the named resource
|
---|
917 | * @throws IOException if I/O errors occur in the process
|
---|
918 | * @since 1.2
|
---|
919 | */
|
---|
920 | protected Enumeration findResources(String name) throws IOException
|
---|
921 | {
|
---|
922 | return Collections.enumeration(Collections.EMPTY_LIST);
|
---|
923 | }
|
---|
924 |
|
---|
925 | /**
|
---|
926 | * Set the default assertion status for classes loaded by this classloader,
|
---|
927 | * used unless overridden by a package or class request.
|
---|
928 | *
|
---|
929 | * @param enabled true to set the default to enabled
|
---|
930 | * @see #setClassAssertionStatus(String, boolean)
|
---|
931 | * @see #setPackageAssertionStatus(String, boolean)
|
---|
932 | * @see #clearAssertionStatus()
|
---|
933 | * @since 1.4
|
---|
934 | */
|
---|
935 | public void setDefaultAssertionStatus(boolean enabled)
|
---|
936 | {
|
---|
937 | defaultAssertionStatus = enabled;
|
---|
938 | }
|
---|
939 |
|
---|
940 | /**
|
---|
941 | * Set the default assertion status for packages, used unless overridden
|
---|
942 | * by a class request. This default also covers subpackages, unless they
|
---|
943 | * are also specified. The unnamed package should use null for the name.
|
---|
944 | *
|
---|
945 | * @param name the package (and subpackages) to affect
|
---|
946 | * @param enabled true to set the default to enabled
|
---|
947 | * @see #setDefaultAssertionStatus(String, boolean)
|
---|
948 | * @see #setClassAssertionStatus(String, boolean)
|
---|
949 | * @see #clearAssertionStatus()
|
---|
950 | * @since 1.4
|
---|
951 | */
|
---|
952 | public synchronized void setPackageAssertionStatus(String name,
|
---|
953 | boolean enabled)
|
---|
954 | {
|
---|
955 | if (packageAssertionStatus == null)
|
---|
956 | packageAssertionStatus
|
---|
957 | = new HashMap(systemPackageAssertionStatus);
|
---|
958 | packageAssertionStatus.put(name, Boolean.valueOf(enabled));
|
---|
959 | }
|
---|
960 |
|
---|
961 | /**
|
---|
962 | * Set the default assertion status for a class. This only affects the
|
---|
963 | * status of top-level classes, any other string is harmless.
|
---|
964 | *
|
---|
965 | * @param name the class to affect
|
---|
966 | * @param enabled true to set the default to enabled
|
---|
967 | * @throws NullPointerException if name is null
|
---|
968 | * @see #setDefaultAssertionStatus(String, boolean)
|
---|
969 | * @see #setPackageAssertionStatus(String, boolean)
|
---|
970 | * @see #clearAssertionStatus()
|
---|
971 | * @since 1.4
|
---|
972 | */
|
---|
973 | public synchronized void setClassAssertionStatus(String name,
|
---|
974 | boolean enabled)
|
---|
975 | {
|
---|
976 | if (classAssertionStatus == null)
|
---|
977 | classAssertionStatus = new HashMap(systemClassAssertionStatus);
|
---|
978 | // The toString() hack catches null, as required.
|
---|
979 | classAssertionStatus.put(name.toString(), Boolean.valueOf(enabled));
|
---|
980 | }
|
---|
981 |
|
---|
982 | /**
|
---|
983 | * Resets the default assertion status of this classloader, its packages
|
---|
984 | * and classes, all to false. This allows overriding defaults inherited
|
---|
985 | * from the command line.
|
---|
986 | *
|
---|
987 | * @see #setDefaultAssertionStatus(boolean)
|
---|
988 | * @see #setClassAssertionStatus(String, boolean)
|
---|
989 | * @see #setPackageAssertionStatus(String, boolean)
|
---|
990 | * @since 1.4
|
---|
991 | */
|
---|
992 | public synchronized void clearAssertionStatus()
|
---|
993 | {
|
---|
994 | defaultAssertionStatus = false;
|
---|
995 | packageAssertionStatus = new HashMap();
|
---|
996 | classAssertionStatus = new HashMap();
|
---|
997 | }
|
---|
998 | }
|
---|