diff options
author | green <green@138bc75d-0d04-0410-961f-82ee72b054a4> | 1999-08-08 14:06:23 +0000 |
---|---|---|
committer | green <green@138bc75d-0d04-0410-961f-82ee72b054a4> | 1999-08-08 14:06:23 +0000 |
commit | 9a6624c49770e9b5e630a7c51eb0a13002d9df83 (patch) | |
tree | 277498eeeff558237a9cd88b0ea8b3788b31d645 /libjava/java/lang/ClassLoader.java | |
parent | 47c5fab6136c7525f4abe013644d7d20570d1b94 (diff) | |
download | gcc-9a6624c49770e9b5e630a7c51eb0a13002d9df83.tar.gz |
1999-08-09 Anthony Green <green@cygnus.com>
* gij.cc: New file.
* include/config.h.in: Rebuilt.
* acconfig.h: Add INTERPRETER.
* configure: Rebuilt.
* Makefile.in: Rebuilt.
* Makefile.am (libffi_files): Identify the libffi object files for
inclusion in libgcj.
(LIBFFIINCS): Define.
* interpret.cc (gnu::gcj::runtime::MethodInvocation::continue1):
Dummy definition for configurations without an interpreter.
* java/net/natPlainSocketImpl.cc (getOption): Disamiguate call to
java::lang::Boolean constructor.
* include/java-interp.h: Always include java-cpool.h.
* java/lang/natClassLoader.cc (getVMClassLoader0): Always return 0
when INTERPRETER not defined.
* java/lang/Class.h (finalize): Define.
* gnu/gcj/util/path/DirectoryPathEntry.java (getURL): Catch
IOException from File.getCanonicalPath.
(getStream): Likewise.
* NEWS: More news.
* THANKS: More thanks.
1999-08-09 Kresten Krab Thorup <krab@gnu.org>
* resolve.cc (get_ffi_type_from_signature): Generate uint16 for
jchar type.
(_Jv_PrepareClass): Allow non-abstract classes to
have abstract subclasses.
(_Jv_ResolvePoolEntry): Revert subclass check for protected
fields and methods.
* interpret.cc (continue1/perform_invoke): Don't sign extend
uint16 return val.
(continue1/lshl,lshr): Push long, not int.
(continue1/ulshr): Use UINT64, not long long.
* defineclass.cc (handleFieldsEnd): Handle case when all fields
are static.
* java/lang/natClass.cc (forName): Add call to _Jv_InitClass.
* java/lang/FirstThread.java (run): Add top-level exception
handler.
(run0): Renamed from run.
1999-08-08 Kresten Krab Thorup <krab@gnu.org>
* configure.in (--with-interpreter): Added.
* include/config.h.in (INTERPRETER): Added.
* java/lang/ClassLoader.java: File replaced.
* java/lang/VMClassLoader.java: New file.
* java/lang/natClassLoader.cc: New file.
* gnu/gcj/runtime/MethodInvocation.java: New file.
* gnu/gcj/util/path/SearchPath.java: New file.
* gnu/gcj/util/path/PathEntry.java: New file.
* gnu/gcj/util/path/DirectoryPathEntry.java: New file.
* gnu/gcj/util/path/ZipPathEntry.java: New file.
* gnu/gcj/util/path/URLPathEntry.java: New file.
* gnu/gcj/util/path/CacheEntry.java: New file.
* include/java-interp.h: New file.
* include/java-cpool.h: New file.
* include/java-insns.h: New file.
* defineclass.cc: New file.
* interpret.cc: New file.
* resolve.cc: New file.
* java/lang/natClass.cc (loaded_classes, _Jv_RegisterClass,
_Jv_RegisterClasses, _Jv_FindClassInCache, _Jv_FindClass,
_Jv_NewClass, _Jv_FindArrayClass): Moved to natClassLoader.cc.
(finalize): New.
(STATE_NOTHING, STATE_RESOLVED, STATE_IN_PROGRESS, STATE_DONE,
STATE_ERROR): Moved to java/lang/Class.h and renamed with JV_
prefix.
(initializeClass): Use new JV_ prefixed names. Also, call
ClassLoader::resolveClass instead of _Jv_ResolveClass.
* java/lang/Class.h (JV_STATE_PRELOADING, JV_STATE_LOADING,
JV_STATE_LOADED, JV_STATE_COMPILED, JV_STATE_PREPARED,
JV_STATE_LINKED): New.
(_Jv_WaitForState, _Jv_RegisterInitiatingLoader,
_Jv_UnregisterClass, _Jv_InternClassStrings): New friends.
(_Jv_IsInterpretedClass, _Jv_InitField, _Jv_LookupDeclaredMethod,
_Jv_DetermineVTableIndex, _Jv_ResolvePoolEntry, _Jv_PrepareClass,
_Jv_ClassReader, _Jv_InterpClass, _Jv_InterpMethod,
_Jv_InterpMethodInvocation): New friends for interpreter.
(finalize): New.
(CONSTANT_Class, CONSTANT_String, etc.): Moved to
include/java-cpool.h and renamed with JV_ prefix.
* include/jvm.h (_Jv_makeUtf8Const, _Jv_makeUtf8TypeConst): New
decls.
(_Jv_UnregisterClass): New decl.
* java/lang/natClassLoader.cc (_Jv_FindArrayClass): Added
class loader argument.
(_Jv_FindClass): Use class loader.
* prims.cc (_Jv_makeUtf8Const): New function.
(_Jv_NewObjectArray): Change use of _Jv_FindArrayClass.
(_Jv_NewPrimArray): Ditto.
(_Jv_FindClassFromSignature): Ditto.
* java/lang/reflect/natArray.cc (newInstance): Ditto.
* java/lang/reflect/natMethod.cc (getType): Ditto.
* include/java-field.h (_Jv_Field::isRef): Make robust for
non-resolved contexts.
* boehm.cc (_Jv_MarkObj): Mark interpreter-related fields.
Also, don't mark class->next field.
* java/lang/VirtualMachineError.java: Added FIXME note.
* configure.in (INTERPSPEC): New spec.
* libgcj.spec.in: Added INTERPSPEC.
* Makefile.am: Added gcjh friends for java/lang/VMClassLoader and
gnu/gcj/runtime/MethodInvocation.
(libgcj_la_SOURCES): Added resolve.cc defineclass.cc interpret.cc.
(ordinary_java_source_files): Added above mentioned java classes.
* configure: Rebuilt.
* Makefile.in: Rebuilt.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@28597 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libjava/java/lang/ClassLoader.java')
-rw-r--r-- | libjava/java/lang/ClassLoader.java | 426 |
1 files changed, 367 insertions, 59 deletions
diff --git a/libjava/java/lang/ClassLoader.java b/libjava/java/lang/ClassLoader.java index 048cea7d883..f0b533f6041 100644 --- a/libjava/java/lang/ClassLoader.java +++ b/libjava/java/lang/ClassLoader.java @@ -9,86 +9,394 @@ Libgcj License. Please consult the file "LIBGCJ_LICENSE" for details. */ package java.lang; + import java.io.InputStream; -import java.util.Hashtable; +import java.net.URL; +import java.net.URLConnection; +import java.util.Stack; /** - * @author Tom Tromey <tromey@cygnus.com> - * @date October 28, 1998 + * The class <code>ClassLoader</code> is intended to be subclassed by + * applications in order to describe new ways of loading classes, + * such as over the network. + * + * @author Kresten Krab Thorup */ /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 * Status: Just a stub; not useful at all. */ -public abstract class ClassLoader -{ - protected ClassLoader () - { - cache = new Hashtable (); - } +public abstract class ClassLoader { - protected final Class defineClass (String className, byte[] bytecode, - int offset, int length) - { - throw new ClassFormatError ("defineClass unimplemented"); - } + static private ClassLoader system; + + private static native ClassLoader getVMClassLoader0 (); - protected final Class defineClass (byte[] bytecodes, - int offset, int length) - { - return defineClass (null, bytecodes, offset, length); - } + static public ClassLoader getSystemClassLoader () { + if (system == null) + system = getVMClassLoader0 (); + return system; + } - protected final Class findLoadedClass (String className) - { - return (Class) cache.get(className); - } + /** + * Creates a <code>ClassLoader</code>. The only thing this + * constructor does, is to call + * <code>checkCreateClassLoader</code> on the current + * security manager. + * @exception java.lang.SecurityException if not allowed + */ + protected ClassLoader() + { + SecurityManager security = System.getSecurityManager (); + if (security != null) + security.checkCreateClassLoader (); + } - protected final Class findSystemClass (String className) - throws ClassNotFoundException - { - Class c = system.findLoadedClass(className); - system.resolveClass(c); - return c; - } + /** + * Loads and link the class by the given name. + * @param name the name of the class. + * @return the class loaded. + * @see ClassLoader#loadClass(String,boolean) + * @exception java.lang.ClassNotFoundException + */ + public Class loadClass(String name) + throws java.lang.ClassNotFoundException, java.lang.LinkageError + { + return loadClass (name, true); + } - // FIXME: Needs URL. - // public URL getResource (String resName); + /** + * Loads the class by the given name. + * As per java 1.1, this has been deprecated. Use + * <code>loadClass(String)</code> + * instead. + * @param name the name of the class. + * @param link if the class should be linked. + * @return the class loaded. + * @exception java.lang.ClassNotFoundException + * @deprecated + */ + protected abstract Class loadClass(String name, boolean link) + throws java.lang.ClassNotFoundException, java.lang.LinkageError; - public InputStream getResourceAsStream (String resName) - { - return null; - } + /** + * Defines a class, given the class-data. According to the JVM, this + * method should not be used; instead use the variant of this method + * in which the name of the class being defined is specified + * explicitly. + * <P> + * If the name of the class, as specified (implicitly) in the class + * data, denotes a class which has already been loaded by this class + * loader, an instance of + * <code>java.lang.ClassNotFoundException</code> will be thrown. + * + * @param data bytes in class file format. + * @param off offset to start interpreting data. + * @param len length of data in class file. + * @return the class defined. + * @exception java.lang.ClassNotFoundException + * @exception java.lang.LinkageError + * @see ClassLoader#defineClass(String,byte[],int,int) */ + protected final Class defineClass(byte[] data, int off, int len) + throws java.lang.ClassNotFoundException, java.lang.LinkageError + { + return defineClass (null, data, off, len); + } - // FIXME: Needs URL. - // public static final URL getSystemResource (String resName); + /** + * Defines a class, given the class-data. This is preferable + * over <code>defineClass(byte[],off,len)</code> since it is more + * secure. If the expected name does not match that of the class + * file, <code>ClassNotFoundException</code> is thrown. If + * <code>name</code> denotes the name of an already loaded class, a + * <code>LinkageError</code> is thrown. + * <p> + * + * FIXME: How do we assure that the class-file data is not being + * modified, simultaneously with the class loader running!? If this + * was done in some very clever way, it might break security. + * Right now I am thinking that defineclass should make sure never to + * read an element of this array more than once, and that that would + * assure the ``immutable'' appearance. It is still to be determined + * if this is in fact how defineClass operates. + * + * @param name the expected name. + * @param data bytes in class file format. + * @param off offset to start interpreting data. + * @param len length of data in class file. + * @return the class defined. + * @exception java.lang.ClassNotFoundException + * @exception java.lang.LinkageError + */ + protected final synchronized Class defineClass(String name, + byte[] data, + int off, + int len) + throws java.lang.ClassNotFoundException, java.lang.LinkageError + { + if (data==null || data.length < off+len || off<0 || len<0) + throw new ClassFormatError ("arguments to defineClass " + + "are meaningless"); - public static final InputStream getSystemResourceAsStream (String resName) - { - return null; - } + // as per 5.3.5.1 + if (name != null && findLoadedClass (name) != null) + throw new java.lang.LinkageError ("class " + + name + + " already loaded"); - protected abstract Class loadClass (String className, boolean resolve) - throws ClassNotFoundException; - public Class loadClass (String name) throws ClassNotFoundException - { - return loadClass (name, true); - } + try { + // Since we're calling into native code here, + // we better make sure that any generated + // exception is to spec! + + return defineClass0 (name, data, off, len); + + } catch (java.lang.LinkageError x) { + throw x; // rethrow + + } catch (java.lang.ClassNotFoundException x) { + throw x; // rethrow + + } catch (java.lang.VirtualMachineError x) { + throw x; // rethrow + + } catch (java.lang.Throwable x) { + // This should never happen, or we are beyond spec. + + throw new InternalError ("Unexpected exception " + + "while defining class " + + name + ": " + + x.toString ()); + } + } + + /** This is the entry point of defineClass into the native code */ + private native Class defineClass0 (String name, + byte[] data, + int off, + int len) + throws java.lang.ClassNotFoundException, java.lang.LinkageError; - protected final void resolveClass (Class c) - { - // Nothing for now. - } - protected final void setSigners (Class cl, Object[] signers) - { - // Nothing for now. + /** This is called by defineClass0, once the "raw" and uninitialized + * class object has been created, and handles exceptions generated + * while actually defining the class (_Jv_DefineClass). defineClass0 + * holds the lock on the new class object, so it needs to capture + * these exceptions. */ + + private static Throwable defineClass1 (Class klass, byte[] data, + int offset, int length) + { + try { + defineClass2 (klass, data, offset, length); + } catch (Throwable x) { + return x; } + return null; + } + + /** This is just a wrapper for _Jv_DefineClass */ + private static native void defineClass2 (Class klass, byte[] data, + int offset, int length) + throws Throwable; + + /** + * Link the given class. This will bring the class to a state where + * the class initializer can be run. Linking involves the following + * steps: + * <UL> + * <LI> Prepare (allocate and internalize) the constant strings that + * are used in this class. + * <LI> Allocate storage for static fields, and define the layout + * of instance fields. + * <LI> Perform static initialization of ``static final'' int, + * long, float, double and String fields for which there is a + * compile-time constant initializer. + * <LI> Create the internal representation of the ``vtable''. + * </UL> + * For <code>gcj</code>-compiled classes, only the first step is + * performed. The compiler will have done the rest already. + * <P> + * This is called by the system automatically, + * as part of class initialization; there is no reason to ever call + * this method directly. + * <P> + * For historical reasons, this method has a name which is easily + * misunderstood. Java classes are never ``resolved''. Classes are + * linked; whereas method and field references are resolved. + * <P> + * FIXME: The JDK documentation declares this method + * <code>final</code>, we declare it <code>static</code> -- any + * objections? This allows us to call it directly from native code + * with less hassle. + * + * @param clazz the class to link. + * @exception java.lang.LinkageError + */ + protected static void resolveClass(Class clazz) + throws java.lang.LinkageError + { + synchronized (clazz) + { + try { + linkClass0 (clazz); + } catch (Throwable x) { + markClassErrorState0 (clazz); + + if (x instanceof Error) + throw (Error)x; + else + throw new java.lang.InternalError + ("unexpected exception during linking: " + x); + } + } + } + + /** Internal method. Calls _Jv_PrepareClass and + * _Jv_InternClassStrings. This is only called from resolveClass. */ + private static native void linkClass0(Class clazz) + throws java.lang.LinkageError; + + /** Internal method. Marks the given clazz to be in an erroneous + * state, and calls notifyAll() on the class object. This should only + * be called when the caller has the lock on the class object. */ + private static native void markClassErrorState0(Class clazz); + + + /** + * Returns a class found in a system-specific way, typically + * via the <code>java.class.path</code> system property. + * + * @param name the class to resolve. + * @return the class loaded. + * @exception java.lang.LinkageError + * @exception java.lang.ClassNotFoundException + */ + protected native static Class findSystemClass(String name) + throws java.lang.ClassNotFoundException, java.lang.LinkageError; + + /* + * Does currently nothing. + */ + protected final void setSigners(Class claz, Object[] signers) { + /* claz.setSigners (signers); */ + } + + /* + * If a class named <code>name</code> was previously loaded using + * this <code>ClassLoader</code>, then it is returned. Otherwise + * it returns <code>null</code>. + * @param name class to find. + * @return the class loaded, or null. + */ + protected native Class findLoadedClass(String name); - // Class cache. - private Hashtable cache; + public static final InputStream getSystemResourceAsStream(String name) { + return system.getResourceAsStream (name); + } - // The system class loader. FIXME: should have an actual value - private static final ClassLoader system = null; + public static final URL getSystemResource(String name) { + return system.getResource (name); + } + + public static final byte[] getSystemResourceAsBytes(String name) { + return system.getResourceAsBytes (name); + } + + /** + * Return an InputStream representing the resource name. + * This is essentially like + * <code>getResource(name).openStream()</code>, except + * it masks out any IOException and returns null on failure. + * @param name resource to load + * @return an InputStream, or null + * @see java.lang.ClassLoader#getResource(String) + * @see java.lang.ClassLoader#getResourceAsBytes(String) + * @see java.io.InputStream + */ + public InputStream getResourceAsStream(String name) + { + try { + URL res = getResource (name); + if (res == null) return null; + return res.openStream (); + } catch (java.io.IOException x) { + return null; + } + } + + /** + * Return a byte array <code>byte[]</code> representing the + * resouce <code>name</code>. This only works for resources + * that have a known <code>content-length</code>, and + * it will block while loading the resource. Returns null + * for error conditions.<p> + * Since it is synchroneous, this is only convenient for + * resources that are "readily" available. System resources + * can conveniently be loaded this way, and the runtime + * system uses this to load class files. <p> + * To find the class data for a given class, use + * something like the following: + * <ul><code> + * String res = clazz.getName().replace ('.', '/')) + ".class";<br> + * byte[] data = getResourceAsBytes (res); + * </code></ul> + * @param name resource to load + * @return a byte array, or null + * @see java.lang.ClassLoader#getResource(String) + * @see java.lang.ClassLoader#getResourceAsStream(String) + */ + public byte[] getResourceAsBytes(String name) { + try { + URL res = getResource (name); + if (res == null) return null; + URLConnection conn = res.openConnection (); + int len = conn.getContentLength (); + if (len == -1) return null; + return readbytes (conn.getInputStream (), len); + } catch (java.io.IOException x) { + return null; + } + } + + /** + * Return an java.io.URL representing the resouce <code>name</code>. + * @param name resource to load + * @return a URL, or null if there is no such resource. + * @see java.lang.ClassLoader#getResourceAsBytes(String) + * @see java.lang.ClassLoader#getResourceAsStream(String) + * @see java.io.URL + */ + public URL getResource(String name) { + return null; + } + + /** + * Utility routine to read a resource fully, even if the given + * InputStream only provides partial results. + */ + private static byte[] readbytes (InputStream is, int length) + { + try { + + byte[] data = new byte[length]; + int read; + int off = 0; + + while (off != length) + { + read = is.read (data, off, (int) (length-off)); + + if (read == -1) + return null; + + off += read; + } + + return data; + } catch (java.io.IOException x) { + return null; + } + } } |