OSDN Git Service

1999-08-09 Anthony Green <green@cygnus.com>
[pf3gnuchains/gcc-fork.git] / libjava / java / lang / ClassLoader.java
1 // ClassLoader.java - Define policies for loading Java classes.
2
3 /* Copyright (C) 1998, 1999  Cygnus Solutions
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.net.URL;
15 import java.net.URLConnection;
16 import java.util.Stack;
17
18 /**
19  * The class <code>ClassLoader</code> is intended to be subclassed by
20  * applications in order to describe new ways of loading classes,
21  * such as over the network.
22  *
23  * @author  Kresten Krab Thorup
24  */
25
26 /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
27  * Status: Just a stub; not useful at all.
28  */
29
30 public abstract class ClassLoader {
31
32   static private ClassLoader system;
33     
34   private static native ClassLoader getVMClassLoader0 ();
35
36   static public ClassLoader getSystemClassLoader () {
37     if (system == null)
38       system = getVMClassLoader0 ();
39     return system;
40   }
41
42   /**
43    * Creates a <code>ClassLoader</code>.   The only thing this
44    * constructor does, is to call
45    * <code>checkCreateClassLoader</code> on the current 
46    * security manager. 
47    * @exception java.lang.SecurityException if not allowed
48    */
49   protected ClassLoader() 
50   {
51     SecurityManager security = System.getSecurityManager ();
52     if (security != null)
53       security.checkCreateClassLoader ();
54   }
55
56   /** 
57    * Loads and link the class by the given name.
58    * @param     name the name of the class.
59    * @return    the class loaded.
60    * @see       ClassLoader#loadClass(String,boolean)
61    * @exception java.lang.ClassNotFoundException 
62    */ 
63   public Class loadClass(String name) 
64     throws java.lang.ClassNotFoundException, java.lang.LinkageError
65   { 
66     return loadClass (name, true);
67   }
68
69   /** 
70    * Loads the class by the given name.  
71    * As per java 1.1, this has been deprecated.  Use 
72    * <code>loadClass(String)</code>
73    * instead.
74    * @param     name the name of the class.
75    * @param     link if the class should be linked.
76    * @return    the class loaded.
77    * @exception java.lang.ClassNotFoundException 
78    * @deprecated 
79    */ 
80   protected abstract Class loadClass(String name, boolean link)
81     throws java.lang.ClassNotFoundException, java.lang.LinkageError;
82
83   /** 
84    * Defines a class, given the class-data.  According to the JVM, this
85    * method should not be used; instead use the variant of this method
86    * in which the name of the class being defined is specified
87    * explicitly.   
88    * <P>
89    * If the name of the class, as specified (implicitly) in the class
90    * data, denotes a class which has already been loaded by this class
91    * loader, an instance of
92    * <code>java.lang.ClassNotFoundException</code> will be thrown.
93    *
94    * @param     data    bytes in class file format.
95    * @param     off     offset to start interpreting data.
96    * @param     len     length of data in class file.
97    * @return    the class defined.
98    * @exception java.lang.ClassNotFoundException 
99    * @exception java.lang.LinkageError
100    * @see ClassLoader#defineClass(String,byte[],int,int) */
101   protected final Class defineClass(byte[] data, int off, int len) 
102     throws java.lang.ClassNotFoundException, java.lang.LinkageError
103   {
104     return defineClass (null, data, off, len);
105   }
106
107   /** 
108    * Defines a class, given the class-data.  This is preferable
109    * over <code>defineClass(byte[],off,len)</code> since it is more
110    * secure.  If the expected name does not match that of the class
111    * file, <code>ClassNotFoundException</code> is thrown.  If
112    * <code>name</code> denotes the name of an already loaded class, a
113    * <code>LinkageError</code> is thrown.
114    * <p>
115    * 
116    * FIXME: How do we assure that the class-file data is not being
117    * modified, simultaneously with the class loader running!?  If this
118    * was done in some very clever way, it might break security.  
119    * Right now I am thinking that defineclass should make sure never to
120    * read an element of this array more than once, and that that would
121    * assure the ``immutable'' appearance.  It is still to be determined
122    * if this is in fact how defineClass operates.
123    *
124    * @param     name    the expected name.
125    * @param     data    bytes in class file format.
126    * @param     off     offset to start interpreting data.
127    * @param     len     length of data in class file.
128    * @return    the class defined.
129    * @exception java.lang.ClassNotFoundException 
130    * @exception java.lang.LinkageError
131    */
132   protected final synchronized Class defineClass(String name,
133                                                  byte[] data,
134                                                  int off,
135                                                  int len)
136     throws java.lang.ClassNotFoundException, java.lang.LinkageError
137   {
138     if (data==null || data.length < off+len || off<0 || len<0)
139       throw new ClassFormatError ("arguments to defineClass "
140                                   + "are meaningless");
141
142     // as per 5.3.5.1
143     if (name != null  &&  findLoadedClass (name) != null)
144       throw new java.lang.LinkageError ("class " 
145                                         + name 
146                                         + " already loaded");
147
148     try {
149       // Since we're calling into native code here, 
150       // we better make sure that any generated
151       // exception is to spec!
152
153       return defineClass0 (name, data, off, len);
154
155     } catch (java.lang.LinkageError x) {
156       throw x;          // rethrow
157
158     } catch (java.lang.ClassNotFoundException x) {
159       throw x;          // rethrow
160
161     } catch (java.lang.VirtualMachineError x) {
162       throw x;          // rethrow
163
164     } catch (java.lang.Throwable x) {
165       // This should never happen, or we are beyond spec.  
166       
167       throw new InternalError ("Unexpected exception "
168                                + "while defining class "
169                                + name + ": " 
170                                + x.toString ());
171      }
172   }
173
174   /** This is the entry point of defineClass into the native code */
175   private native Class defineClass0 (String name,
176                                      byte[] data,
177                                      int off,
178                                      int len)
179     throws java.lang.ClassNotFoundException, java.lang.LinkageError;
180
181
182   /** This is called by defineClass0, once the "raw" and uninitialized
183    * class object has been created, and handles exceptions generated
184    * while actually defining the class (_Jv_DefineClass).  defineClass0
185    * holds the lock on the new class object, so it needs to capture
186    * these exceptions.  */
187
188   private static Throwable defineClass1 (Class klass, byte[] data,
189                                          int offset, int length)
190   {
191     try {
192       defineClass2 (klass, data, offset, length);
193     } catch (Throwable x) {
194       return x;
195     }
196     return null;
197   }
198  
199   /** This is just a wrapper for _Jv_DefineClass */
200   private static native void defineClass2 (Class klass, byte[] data, 
201                                     int offset, int length)
202     throws Throwable;
203
204   /** 
205    * Link the given class.  This will bring the class to a state where
206    * the class initializer can be run.  Linking involves the following
207    * steps: 
208    * <UL>
209    * <LI>  Prepare (allocate and internalize) the constant strings that
210    *       are used in this class.
211    * <LI>  Allocate storage for static fields, and define the layout
212    *       of instance fields.
213    * <LI>  Perform static initialization of ``static final'' int,
214    *       long, float, double and String fields for which there is a
215    *       compile-time constant initializer.
216    * <LI>  Create the internal representation of the ``vtable''.
217    * </UL>
218    * For <code>gcj</code>-compiled classes, only the first step is
219    * performed.  The compiler will have done the rest already.
220    * <P>
221    * This is called by the system automatically,
222    * as part of class initialization; there is no reason to ever call
223    * this method directly.  
224    * <P> 
225    * For historical reasons, this method has a name which is easily
226    * misunderstood.  Java classes are never ``resolved''.  Classes are
227    * linked; whereas method and field references are resolved.
228    * <P>
229    * FIXME: The JDK documentation declares this method
230    * <code>final</code>, we declare it <code>static</code> -- any
231    * objections?  This allows us to call it directly from native code
232    * with less hassle. 
233    *
234    * @param     clazz the class to link.
235    * @exception java.lang.LinkageError
236    */
237   protected static void resolveClass(Class clazz)
238     throws java.lang.LinkageError
239   {
240     synchronized (clazz)
241       {
242         try {
243           linkClass0 (clazz);
244         } catch (Throwable x) {
245           markClassErrorState0 (clazz);
246
247           if (x instanceof Error)
248             throw (Error)x;
249           else    
250             throw new java.lang.InternalError
251               ("unexpected exception during linking: " + x);
252         }
253       }
254   }
255
256   /** Internal method.  Calls _Jv_PrepareClass and
257    * _Jv_InternClassStrings.  This is only called from resolveClass.  */ 
258   private static native void linkClass0(Class clazz)
259     throws java.lang.LinkageError;
260
261   /** Internal method.  Marks the given clazz to be in an erroneous
262    * state, and calls notifyAll() on the class object.  This should only
263    * be called when the caller has the lock on the class object.  */
264   private static native void markClassErrorState0(Class clazz);
265
266
267   /** 
268    * Returns a class found in a system-specific way, typically
269    * via the <code>java.class.path</code> system property.  
270    *
271    * @param     name the class to resolve.
272    * @return    the class loaded.
273    * @exception java.lang.LinkageError 
274    * @exception java.lang.ClassNotFoundException 
275    */
276   protected native static Class findSystemClass(String name) 
277     throws java.lang.ClassNotFoundException, java.lang.LinkageError;
278
279   /*
280    * Does currently nothing.
281    */ 
282   protected final void setSigners(Class claz, Object[] signers) {
283     /* claz.setSigners (signers); */
284   }
285
286   /*
287    * If a class named <code>name</code> was previously loaded using
288    * this <code>ClassLoader</code>, then it is returned.  Otherwise
289    * it returns <code>null</code>.
290    * @param     name  class to find.
291    * @return    the class loaded, or null.
292    */ 
293   protected native Class findLoadedClass(String name);
294
295   public static final InputStream getSystemResourceAsStream(String name) {
296     return system.getResourceAsStream (name);
297   }
298
299   public static final URL getSystemResource(String name) {
300     return system.getResource (name);
301   }
302
303   public static final byte[] getSystemResourceAsBytes(String name) {
304     return system.getResourceAsBytes (name);
305   }
306
307   /**
308    *   Return an InputStream representing the resource name.  
309    *   This is essentially like 
310    *   <code>getResource(name).openStream()</code>, except
311    *   it masks out any IOException and returns null on failure.
312    * @param   name  resource to load
313    * @return  an InputStream, or null
314    * @see     java.lang.ClassLoader#getResource(String)
315    * @see     java.lang.ClassLoader#getResourceAsBytes(String)
316    * @see     java.io.InputStream
317    */
318   public InputStream getResourceAsStream(String name) 
319   {
320     try {
321       URL res = getResource (name);
322       if (res == null) return null;
323       return res.openStream ();
324     } catch (java.io.IOException x) {
325        return null;
326      }
327   }
328  
329   /**
330    *  Return a byte array <code>byte[]</code> representing the
331    *  resouce <code>name</code>.  This only works for resources
332    *  that have a known <code>content-length</code>, and
333    *  it will block while loading the resource.  Returns null
334    *  for error conditions.<p>
335    *  Since it is synchroneous, this is only convenient for 
336    *  resources that are "readily" available.  System resources
337    *  can conveniently be loaded this way, and the runtime
338    *  system uses this to load class files.  <p>
339    *  To find the class data for a given class, use
340    *  something like the following:
341    *  <ul><code>
342    *  String res = clazz.getName().replace ('.', '/')) + ".class";<br>
343    *  byte[] data = getResourceAsBytes (res);
344    *  </code></ul>
345    * @param   name  resource to load
346    * @return  a byte array, or null
347    * @see     java.lang.ClassLoader#getResource(String)
348    * @see     java.lang.ClassLoader#getResourceAsStream(String)
349    */
350   public byte[] getResourceAsBytes(String name) {
351     try {
352       URL res = getResource (name);
353       if (res == null) return null;
354       URLConnection conn = res.openConnection ();
355       int len = conn.getContentLength ();
356       if (len == -1) return null;
357       return readbytes (conn.getInputStream (), len);
358     } catch (java.io.IOException x) {
359        return null;
360      }
361   }
362  
363   /**
364    * Return an java.io.URL representing the resouce <code>name</code>.  
365    * @param   name  resource to load
366    * @return  a URL, or null if there is no such resource.
367    * @see     java.lang.ClassLoader#getResourceAsBytes(String)
368    * @see     java.lang.ClassLoader#getResourceAsStream(String)
369    * @see     java.io.URL
370    */
371   public URL getResource(String name) {
372     return null;
373   }
374
375   /**
376    * Utility routine to read a resource fully, even if the given
377    * InputStream only provides partial results.
378    */
379   private static byte[] readbytes (InputStream is, int length)
380   {
381     try {
382
383       byte[] data = new byte[length];
384       int read; 
385       int off = 0;
386             
387       while (off != length)
388         {
389           read = is.read (data, off, (int) (length-off));
390
391           if (read == -1) 
392             return null;
393
394           off += read;
395         }
396             
397       return data;
398     } catch (java.io.IOException x) {
399       return null;
400     }
401   }
402 }