diff options
author | tromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-09-25 07:46:19 +0000 |
---|---|---|
committer | tromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-09-25 07:46:19 +0000 |
commit | 9897d47f3967dc4110445aca6f42bad2853d5ace (patch) | |
tree | c440653c21ba6d47253f60036888a563bd7f60a2 | |
parent | bfff91869bcb16d229ea843c3ece03c5839b457b (diff) | |
download | gcc-9897d47f3967dc4110445aca6f42bad2853d5ace.tar.gz |
* java/lang/reflect/Proxy.java (generate): Uncomment protection
domain code.
* java/lang/natClassLoader.cc (defineClass): Added `loader'
argument.
(linkClass0): Now in VMClassLoader.
(markClassErrorState0): Likewise.
(getSystemClassLoaderInternal): New method.
* java/lang/natClass.cc (initializeClass): Use
VMClassLoader::resolveClass.
* java/lang/ClassLoader.java: New version, from Classpath.
* java/lang/Class.java (getProtectionDomain):
protectionDomainPermission and unknownProtectionDomain now in
VMClassLoader.
* java/lang/Class.h: VMClassLoader now a friend class.
* gnu/gcj/runtime/VMClassLoader.java (instance): Now
package-private.
* gcj/javaprims.h: Regenerated class list.
* resolve.cc (_Jv_PrepareClass): Use VMClassLoader::resolveClass.
* java/lang/VMClassLoader.java: New version from Classpath;
modified for libgcj use.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@71765 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | libjava/ChangeLog | 23 | ||||
-rw-r--r-- | libjava/gcj/javaprims.h | 35 | ||||
-rw-r--r-- | libjava/gnu/gcj/runtime/VMClassLoader.java | 2 | ||||
-rw-r--r-- | libjava/java/lang/Class.h | 1 | ||||
-rw-r--r-- | libjava/java/lang/Class.java | 4 | ||||
-rw-r--r-- | libjava/java/lang/ClassLoader.java | 1101 | ||||
-rw-r--r-- | libjava/java/lang/VMClassLoader.java | 305 | ||||
-rw-r--r-- | libjava/java/lang/natClass.cc | 3 | ||||
-rw-r--r-- | libjava/java/lang/natClassLoader.cc | 82 | ||||
-rw-r--r-- | libjava/java/lang/reflect/Proxy.java | 11 | ||||
-rw-r--r-- | libjava/resolve.cc | 3 |
11 files changed, 880 insertions, 690 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 79e8d797d42..c98cf130fab 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,26 @@ +2003-09-25 Tom Tromey <tromey@redhat.com> + + * java/lang/reflect/Proxy.java (generate): Uncomment protection + domain code. + * java/lang/natClassLoader.cc (defineClass): Added `loader' + argument. + (linkClass0): Now in VMClassLoader. + (markClassErrorState0): Likewise. + (getSystemClassLoaderInternal): New method. + * java/lang/natClass.cc (initializeClass): Use + VMClassLoader::resolveClass. + * java/lang/ClassLoader.java: New version, from Classpath. + * java/lang/Class.java (getProtectionDomain): + protectionDomainPermission and unknownProtectionDomain now in + VMClassLoader. + * java/lang/Class.h: VMClassLoader now a friend class. + * gnu/gcj/runtime/VMClassLoader.java (instance): Now + package-private. + * gcj/javaprims.h: Regenerated class list. + * resolve.cc (_Jv_PrepareClass): Use VMClassLoader::resolveClass. + * java/lang/VMClassLoader.java: New version from Classpath; + modified for libgcj use. + 2003-09-25 Michael Koch <konqueror@gmx.de> * java/nio/ByteBufferHelper.java: diff --git a/libjava/gcj/javaprims.h b/libjava/gcj/javaprims.h index a9d8b310418..b88b3fe3e71 100644 --- a/libjava/gcj/javaprims.h +++ b/libjava/gcj/javaprims.h @@ -1,6 +1,6 @@ // javaprims.h - Main external header file for libgcj. -*- c++ -*- -/* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation +/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation This file is part of libgcj. @@ -373,6 +373,39 @@ extern "Java" class Manifest; } + namespace logging + { + class ConsoleHandler; + class ErrorManager; + class FileHandler; + class Filter; + class Formatter; + class Handler; + class Level; + class LogManager; + class LogRecord; + class Logger; + class LoggingPermission; + class MemoryHandler; + class SimpleFormatter; + class SocketHandler; + class StreamHandler; + class XMLFormatter; + } + + namespace prefs + { + class AbstractPreferences; + class BackingStoreException; + class InvalidPreferencesFormatException; + class NodeChangeEvent; + class NodeChangeListener; + class PreferenceChangeEvent; + class PreferenceChangeListener; + class Preferences; + class PreferencesFactory; + } + namespace regex { class Matcher; diff --git a/libjava/gnu/gcj/runtime/VMClassLoader.java b/libjava/gnu/gcj/runtime/VMClassLoader.java index ca0f663c9cc..c5cb056570f 100644 --- a/libjava/gnu/gcj/runtime/VMClassLoader.java +++ b/libjava/gnu/gcj/runtime/VMClassLoader.java @@ -90,7 +90,7 @@ public final class VMClassLoader extends java.net.URLClassLoader private int lib_control; // The only VMClassLoader that can exist. - public static VMClassLoader instance = new VMClassLoader(); + static VMClassLoader instance = new VMClassLoader(); private static final int LIB_FULL = 0; private static final int LIB_CACHE = 1; diff --git a/libjava/java/lang/Class.h b/libjava/java/lang/Class.h index 9bcff6fbb55..7fe96d0a01f 100644 --- a/libjava/java/lang/Class.h +++ b/libjava/java/lang/Class.h @@ -290,6 +290,7 @@ private: // Friends classes and functions to implement the ClassLoader friend class java::lang::ClassLoader; + friend class java::lang::VMClassLoader; friend class java::io::ObjectOutputStream; friend class java::io::ObjectInputStream; diff --git a/libjava/java/lang/Class.java b/libjava/java/lang/Class.java index bd776913fdd..86d52be4b87 100644 --- a/libjava/java/lang/Class.java +++ b/libjava/java/lang/Class.java @@ -227,12 +227,12 @@ public final class Class implements Serializable { SecurityManager sm = System.getSecurityManager(); if (sm != null) - sm.checkPermission(ClassLoader.protectionDomainPermission); + sm.checkPermission(VMClassLoader.protectionDomainPermission); ProtectionDomain protectionDomain = getProtectionDomain0(); if (protectionDomain == null) - return ClassLoader.unknownProtectionDomain; + return VMClassLoader.unknownProtectionDomain; else return protectionDomain; } diff --git a/libjava/java/lang/ClassLoader.java b/libjava/java/lang/ClassLoader.java index 008a19e6603..103976758d7 100644 --- a/libjava/java/lang/ClassLoader.java +++ b/libjava/java/lang/ClassLoader.java @@ -1,25 +1,56 @@ -// ClassLoader.java - Define policies for loading Java classes. +/* ClassLoader.java -- responsible for loading classes into the VM + Copyright (C) 1998, 1999, 2001, 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ -/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation - - This file is part of libgcj. - -This software is copyrighted work licensed under the terms of the -Libgcj License. Please consult the file "LIBGCJ_LICENSE" for -details. */ package java.lang; import java.io.InputStream; import java.io.IOException; +import java.lang.reflect.Constructor; import java.net.URL; -import java.security.AllPermission; import java.security.CodeSource; -import java.security.Permission; -import java.security.Permissions; +import java.security.PermissionCollection; import java.security.Policy; import java.security.ProtectionDomain; -import java.util.*; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import gnu.java.util.DoubleEnumeration; +import gnu.java.util.EmptyEnumeration; /** * The ClassLoader is a way of customizing the way Java gets its classes @@ -30,11 +61,11 @@ import java.util.*; * modification! * * <p>Every classloader has a parent classloader that is consulted before - * the 'child' classloader when classes or resources should be loaded. + * the 'child' classloader when classes or resources should be loaded. * This is done to make sure that classes can be loaded from an hierarchy of - * multiple classloaders and classloaders do not accidentially redefine + * multiple classloaders and classloaders do not accidentially redefine * already loaded classes by classloaders higher in the hierarchy. - * + * * <p>The grandparent of all classloaders is the bootstrap classloader, which * loads all the standard system classes as implemented by GNU Classpath. The * other special classloader is the system classloader (also called @@ -78,8 +109,7 @@ import java.util.*; * * @author John Keiser * @author Mark Wielaard - * @author Eric Blake - * @author Kresten Krab Thorup + * @author Eric Blake <ebb9@email.byu.edu> * @see Class * @since 1.0 * @status still missing 1.4 functionality @@ -95,6 +125,50 @@ public abstract class ClassLoader final Map loadedClasses = new HashMap(); /** + * All packages defined by this classloader. It is not private in order to + * allow native code (and trusted subclasses) access to this field. + */ + final Map definedPackages = new HashMap(); + + /** + * The classloader that is consulted before this classloader. + * If null then the parent is the bootstrap classloader. + */ + private final ClassLoader parent; + + /** + * This is true if this classloader was successfully initialized. + * This flag is needed to avoid a class loader attack: even if the + * security manager rejects an attempt to create a class loader, the + * malicious class could have a finalize method which proceeds to + * define classes. + */ + private final boolean initialized; + + /** + * System/Application classloader: defaults to an instance of + * gnu.java.lang.SystemClassLoader, unless the first invocation of + * getSystemClassLoader loads another class loader because of the + * java.system.class.loader property. The initialization of this field + * is somewhat circular - getSystemClassLoader() checks whether this + * field is null in order to bypass a security check. + */ + static final ClassLoader systemClassLoader = + VMClassLoader.getSystemClassLoader(); + + /** + * The default protection domain, used when defining a class with a null + * paramter for the domain. + */ + static final ProtectionDomain defaultProtectionDomain; + static + { + CodeSource cs = new CodeSource(null, null); + PermissionCollection perm = Policy.getPolicy().getPermissions(cs); + defaultProtectionDomain = new ProtectionDomain(cs, perm); + } + + /** * The desired assertion status of classes loaded by this loader, if not * overridden by package or class instructions. */ @@ -136,157 +210,105 @@ public abstract class ClassLoader Map classAssertionStatus; /** - * The classloader that is consulted before this classloader. - * If null then the parent is the bootstrap classloader. - */ - private final ClassLoader parent; - - /** - * All packages defined by this classloader. It is not private in order to - * allow native code (and trusted subclasses) access to this field. - */ - private HashMap definedPackages = new HashMap(); - - /** - * Returns the parent of this classloader. If the parent of this - * classloader is the bootstrap classloader then this method returns - * <code>null</code>. A security check may be performed on - * <code>RuntimePermission("getClassLoader")</code>. + * Create a new ClassLoader with as parent the system classloader. There + * may be a security check for <code>checkCreateClassLoader</code>. * * @throws SecurityException if the security check fails - * @since 1.2 */ - public final ClassLoader getParent () + protected ClassLoader() throws SecurityException { - // Check if we may return the parent classloader - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - { - Class c = VMSecurityManager.getClassContext()[1]; - ClassLoader cl = c.getClassLoader(); - if (cl != null && ! cl.isAncestorOf(this)) - sm.checkPermission(new RuntimePermission("getClassLoader")); - } - return parent; + this(systemClassLoader); } /** - * Returns the system classloader. The system classloader (also called - * the application classloader) is the classloader that was used to - * load the application classes on the classpath (given by the system - * property <code>java.class.path</code>. This is set as the context - * class loader for a thread. The system property - * <code>java.system.class.loader</code>, if defined, is taken to be the - * name of the class to use as the system class loader, which must have - * a public constructor which takes a ClassLoader as a parent; otherwise this - * uses gnu.java.lang.SystemClassLoader. - * - * <p>Note that this is different from the bootstrap classloader that - * actually loads all the real "system" classes (the bootstrap classloader - * is the parent of the returned system classloader). + * Create a new ClassLoader with the specified parent. The parent will + * be consulted when a class or resource is requested through + * <code>loadClass()</code> or <code>getResource()</code>. Only when the + * parent classloader cannot provide the requested class or resource the + * <code>findClass()</code> or <code>findResource()</code> method + * of this classloader will be called. There may be a security check for + * <code>checkCreateClassLoader</code>. * - * <p>A security check will be performed for - * <code>RuntimePermission("getClassLoader")</code> if the calling class - * is not a parent of the system class loader. - * - * @return the system class loader + * @param parent the classloader's parent, or null for the bootstrap + * classloader * @throws SecurityException if the security check fails - * @throws IllegalStateException if this is called recursively - * @throws Error if <code>java.system.class.loader</code> fails to load * @since 1.2 */ - public static ClassLoader getSystemClassLoader () + protected ClassLoader(ClassLoader parent) { - return gnu.gcj.runtime.VMClassLoader.instance; + // May we create a new classloader? + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkCreateClassLoader(); + this.parent = parent; + this.initialized = true; } /** - * Creates a <code>ClassLoader</code> with no parent. - * @exception java.lang.SecurityException if not allowed + * Load a class using this ClassLoader or its parent, without resolving + * it. Calls <code>loadClass(name, false)</code>. + * + * <p>Subclasses should not override this method but should override + * <code>findClass()</code> which is called by this method. + * + * @param name the name of the class relative to this ClassLoader + * @return the loaded class + * @throws ClassNotFoundException if the class cannot be found */ - protected ClassLoader() + public Class loadClass(String name) throws ClassNotFoundException { - this (null); + return loadClass(name, false); } /** - * Creates a <code>ClassLoader</code> with the given parent. - * The parent may be <code>null</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 - * @since 1.2 + * Load a class using this ClassLoader or its parent, possibly resolving + * it as well using <code>resolveClass()</code>. It first tries to find + * out if the class has already been loaded through this classloader by + * calling <code>findLoadedClass()</code>. Then it calls + * <code>loadClass()</code> on the parent classloader (or when there is + * no parent it uses the VM bootclassloader)</code>). If the class is still + * not loaded it tries to create a new class by calling + * <code>findClass()</code>. Finally when <code>resolve</code> is + * <code>true</code> it also calls <code>resolveClass()</code> on the + * newly loaded class. + * + * <p>Subclasses should not override this method but should override + * <code>findClass()</code> which is called by this method. + * + * @param name the fully qualified name of the class to load + * @param resolve whether or not to resolve the class + * @return the loaded class + * @throws ClassNotFoundException if the class cannot be found */ - protected ClassLoader(ClassLoader parent) + protected synchronized Class loadClass(String name, boolean resolve) + throws ClassNotFoundException { - SecurityManager security = System.getSecurityManager (); - if (security != null) - security.checkCreateClassLoader (); - this.parent = parent; - } + // Have we already loaded this class? + Class c = findLoadedClass(name); + if (c != null) + 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 - { - return loadClass (name, false); - } - - /** - * Loads the class by the given name. The default implementation - * will search for the class in the following order (similar to jdk 1.2) - * <ul> - * <li> First <code>findLoadedClass</code>. - * <li> If parent is non-null, <code>parent.loadClass</code>; - * otherwise <code>findSystemClass</code>. - * <li> <code>findClass</code>. - * </ul> - * If <code>link</code> is true, <code>resolveClass</code> is then - * called. <p> Normally, this need not be overridden; override - * <code>findClass</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 - */ - protected Class loadClass(String name, boolean link) - throws java.lang.ClassNotFoundException - { - Class c = findLoadedClass (name); - - if (c == null) + // Can the class be loaded by a parent? + try { - try + if (parent == null) { - ClassLoader cl = parent; - if (parent == null) - cl = gnu.gcj.runtime.VMClassLoader.instance; - if (cl != this) - c = cl.loadClass (name, link); + c = VMClassLoader.loadClass(name, resolve); + if (c != null) + return c; } - catch (ClassNotFoundException ex) + else { - /* ignore, we'll try findClass */; + return parent.loadClass(name, resolve); } } - - if (c == null) - c = findClass (name); - - if (c == null) - throw new ClassNotFoundException (name); - - if (link) - resolveClass (c); - + catch (ClassNotFoundException e) + { + } + // Still not found, we have to do it ourself. + c = findClass(name); + if (resolve) + resolveClass(c); return c; } @@ -331,59 +353,29 @@ public abstract class ClassLoader * @return the requested Class * @throws ClassNotFoundException when the class can not be found * @since 1.2 - */ - protected Class findClass (String name) - throws ClassNotFoundException + */ + protected Class findClass(String name) throws ClassNotFoundException { - throw new ClassNotFoundException (name); + throw new ClassNotFoundException(name); } - // Protection Domain definitions - // FIXME: should there be a special protection domain used for native code? - - // The permission required to check what a classes protection domain is. - static final Permission protectionDomainPermission - = new RuntimePermission("getProtectionDomain"); - // The protection domain returned if we cannot determine it. - static ProtectionDomain unknownProtectionDomain; - // Protection domain to use when a class is defined without one specified. - static ProtectionDomain defaultProtectionDomain; - - static - { - Permissions permissions = new Permissions(); - permissions.add(new AllPermission()); - unknownProtectionDomain = new ProtectionDomain(null, permissions); - - CodeSource cs = new CodeSource(null, null); - defaultProtectionDomain = - new ProtectionDomain(cs, Policy.getPolicy().getPermissions(cs)); - } - - /** - * 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) + /** + * Helper to define a class using a string of bytes. This version is not + * secure. + * + * @param data the data representing the classfile, in classfile format + * @param offset the offset into the data where the classfile starts + * @param len the length of the classfile data in the array + * @return the class that was defined + * @throws ClassFormatError if data is not in proper classfile format + * @throws IndexOutOfBoundsException if offset or len is negative, or + * offset + len exceeds data * @deprecated use {@link #defineClass(String, byte[], int, int)} instead */ - protected final Class defineClass(byte[] data, int off, int len) + protected final Class defineClass(byte[] data, int offset, int len) throws ClassFormatError { - return defineClass (null, data, off, len, defaultProtectionDomain); + return defineClass(null, data, offset, len); } /** @@ -405,351 +397,225 @@ public abstract class ClassLoader * @throws SecurityException if name starts with "java." * @since 1.1 */ - protected final Class defineClass(String name, byte[] data, int off, int len) - throws ClassFormatError + protected final Class defineClass(String name, byte[] data, int offset, + int len) throws ClassFormatError { - return defineClass (name, data, off, len, defaultProtectionDomain); + return defineClass(name, data, offset, len, null); } - - /** - * 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. - * @param protectionDomain security protection domain for the class. - * @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, - ProtectionDomain protectionDomain) + + /** + * Helper to define a class using a string of bytes. Subclasses should call + * this method from their <code>findClass()</code> implementation. If the + * domain is null, the default of + * <code>Policy.getPolicy().getPermissions(new CodeSource(null, null))<code> + * is used. Once a class has been defined in a package, all further classes + * in that package must have the same set of certificates or a + * SecurityException is thrown. + * + * @param name the name to give the class. null if unknown + * @param data the data representing the classfile, in classfile format + * @param offset the offset into the data where the classfile starts + * @param len the length of the classfile data in the array + * @param domain the ProtectionDomain to give to the class, null for the + * default protection domain + * @return the class that was defined + * @throws ClassFormatError if data is not in proper classfile format + * @throws IndexOutOfBoundsException if offset or len is negative, or + * offset + len exceeds data + * @throws SecurityException if name starts with "java.", or if certificates + * do not match up + * @since 1.2 + */ + protected final synchronized Class defineClass(String name, byte[] data, + int offset, int len, + ProtectionDomain domain) throws ClassFormatError { - if (data==null || data.length < off+len || off<0 || len<0) - throw new ClassFormatError ("arguments to defineClass " - + "are meaningless"); - - // as per 5.3.5.1 - if (name != null && findLoadedClass (name) != null) - throw new java.lang.LinkageError ("class " - + name - + " already loaded"); - - if (protectionDomain == null) - protectionDomain = defaultProtectionDomain; - - try - { - Class retval = defineClass0 (name, data, off, len, protectionDomain); - loadedClasses.put(retval.getName(), retval); - return retval; - } - catch (LinkageError x) - { - throw x; // rethrow - } - catch (VirtualMachineError x) - { - throw x; // rethrow - } - catch (Throwable x) - { - // This should never happen, or we are beyond spec. - InternalError r = new InternalError ("Unexpected exception " - + "while defining class " - + name); - r.initCause(x); - throw r; - } + if (domain == null) + domain = defaultProtectionDomain; + if (! initialized) + throw new SecurityException("attempt to define class from uninitialized class loader"); + Class retval = VMClassLoader.defineClass(this, name, data, + offset, len, domain); + loadedClasses.put(retval.getName(), retval); + return retval; } - /** This is the entry point of defineClass into the native code */ - private native Class defineClass0 (String name, - byte[] data, - int off, - int len, - ProtectionDomain protectionDomain) - throws ClassFormatError; - - /** - * 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. - * - * @param clazz the class to link. - * @exception java.lang.LinkageError - */ - protected final void resolveClass(Class clazz) - { - resolveClass0(clazz); - } - - static void resolveClass0(Class clazz) - { - synchronized (clazz) - { - try - { - linkClass0 (clazz); - } - catch (Throwable x) - { - markClassErrorState0 (clazz); - - LinkageError e; - if (x instanceof LinkageError) - e = (LinkageError)x; - else if (x instanceof ClassNotFoundException) - { - e = new NoClassDefFoundError("while resolving class: " - + clazz.getName()); - e.initCause (x); - } - else - { - e = new LinkageError ("unexpected exception during linking: " - + clazz.getName()); - e.initCause (x); - } - throw e; - } - } + /** + * Links the class, if that has not already been done. Linking basically + * resolves all references to other classes made by this class. + * + * @param c the class to resolve + * @throws NullPointerException if c is null + * @throws LinkageError if linking fails + */ + protected final void resolveClass(Class c) + { + VMClassLoader.resolveClass(c); } - /** Internal method. Calls _Jv_PrepareClass and - * _Jv_PrepareCompiledClass. This is only called from resolveClass. */ - private static native void linkClass0(Class clazz); - - /** 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); - /** - * Defines a new package and creates a Package object. - * The package should be defined before any class in the package is - * defined with <code>defineClass()</code>. The package should not yet - * be defined before in this classloader or in one of its parents (which - * means that <code>getPackage()</code> should return <code>null</code>). - * All parameters except the <code>name</code> of the package may be - * <code>null</code>. - * <p> - * Subclasses should call this method from their <code>findClass()</code> - * implementation before calling <code>defineClass()</code> on a Class - * in a not yet defined Package (which can be checked by calling - * <code>getPackage()</code>). - * - * @param name The name of the Package - * @param specTitle The name of the specification - * @param specVendor The name of the specification designer - * @param specVersion The version of this specification - * @param implTitle The name of the implementation - * @param implVendor The vendor that wrote this implementation - * @param implVersion The version of this implementation - * @param sealed If sealed the origin of the package classes - * @return the Package object for the specified package + * Helper to find a Class using the system classloader, possibly loading it. + * A subclass usually does not need to call this, if it correctly + * overrides <code>findClass(String)</code>. * - * @exception IllegalArgumentException if the package name is null or if - * it was already defined by this classloader or one of its parents. - * - * @see Package - * @since 1.2 + * @param name the name of the class to find + * @return the found class + * @throws ClassNotFoundException if the class cannot be found */ - protected Package definePackage(String name, - String specTitle, String specVendor, - String specVersion, String implTitle, - String implVendor, String implVersion, - URL sealed) + protected final Class findSystemClass(String name) + throws ClassNotFoundException { - if (getPackage(name) != null) - throw new IllegalArgumentException("Package " + name - + " already defined"); - Package p = new Package(name, - specTitle, specVendor, specVersion, - implTitle, implVendor, implVersion, - sealed); - synchronized (definedPackages) - { - definedPackages.put(name, p); - } - return p; + return Class.forName(name, false, systemClassLoader); } /** - * Returns the Package object for the requested package name. It returns - * null when the package is not defined by this classloader or one of its - * parents. + * Returns the parent of this classloader. If the parent of this + * classloader is the bootstrap classloader then this method returns + * <code>null</code>. A security check may be performed on + * <code>RuntimePermission("getClassLoader")</code>. * - * @param name the package name to find - * @return the package, if defined + * @throws SecurityException if the security check fails * @since 1.2 */ - protected Package getPackage(String name) + public final ClassLoader getParent() { - Package p; - if (parent == null) - // XXX - Should we use the bootstrap classloader? - p = null; - else - p = parent.getPackage(name); - - if (p == null) + // Check if we may return the parent classloader. + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { - synchronized (definedPackages) - { - p = (Package) definedPackages.get(name); - } + Class c = VMSecurityManager.getClassContext()[1]; + ClassLoader cl = c.getClassLoader(); + if (cl != null && ! cl.isAncestorOf(this)) + sm.checkPermission(new RuntimePermission("getClassLoader")); } - - return p; + return parent; } /** - * Returns all Package objects defined by this classloader and its parents. + * Helper to set the signers of a class. This should be called after + * defining the class. * - * @return an array of all defined packages - * @since 1.2 + * @param c the Class to set signers of + * @param signers the signers to set + * @since 1.1 */ - protected Package[] getPackages() + protected final void setSigners(Class c, Object[] signers) { - Package[] allPackages; - - // Get all our packages. - Package[] packages; - synchronized(definedPackages) - { - packages = new Package[definedPackages.size()]; - definedPackages.values().toArray(packages); - } - - // If we have a parent get all packages defined by our parents. - if (parent != null) - { - Package[] parentPackages = parent.getPackages(); - allPackages = new Package[parentPackages.length + packages.length]; - System.arraycopy(parentPackages, 0, allPackages, 0, - parentPackages.length); - System.arraycopy(packages, 0, allPackages, parentPackages.length, - packages.length); - } - else - // XXX - Should we use the bootstrap classloader? - allPackages = packages; - - return allPackages; + // c.setSigners(signers); } /** - * Called by <code>Runtime.loadLibrary()</code> to get an absolute path - * to a (system specific) library that was requested by a class loaded - * by this classloader. The default implementation returns - * <code>null</code>. It should be implemented by subclasses when they - * have a way to find the absolute path to a library. If this method - * returns null the library is searched for in the default locations - * (the directories listed in the <code>java.library.path</code> system - * property). + * Helper to find an already-loaded class in this ClassLoader. * - * @param name the (system specific) name of the requested library - * @return the full pathname to the requested library, or null - * @see Runtime#loadLibrary() - * @since 1.2 + * @param name the name of the class to find + * @return the found Class, or null if it is not found + * @since 1.1 */ - protected String findLibrary(String name) + protected final synchronized Class findLoadedClass(String name) { - return null; + // NOTE: If the VM is keeping its own cache, it may make sense to have + // this method be native. + return (Class) loadedClasses.get(name); } - /** - * Returns a class found in a system-specific way, typically - * via the <code>java.class.path</code> system property. Loads the - * class if necessary. + /** + * Get the URL to a resource using this classloader or one of its parents. + * First tries to get the resource by calling <code>getResource()</code> + * on the parent classloader. If the parent classloader returns null then + * it tries finding the resource by calling <code>findResource()</code> on + * this classloader. The resource name should be separated by '/' for path + * elements. + * + * <p>Subclasses should not override this method but should override + * <code>findResource()</code> which is called by this method. * - * @param name the class to resolve. - * @return the class loaded. - * @exception java.lang.LinkageError - * @exception java.lang.ClassNotFoundException + * @param name the name of the resource relative to this classloader + * @return the URL to the resource or null when not found */ - protected final Class findSystemClass(String name) - throws java.lang.ClassNotFoundException + public URL getResource(String name) { - return gnu.gcj.runtime.VMClassLoader.instance.loadClass (name); + URL result; + + if (parent == null) + result = VMClassLoader.getResource(name); + else + result = parent.getResource(name); + + if (result == null) + result = findResource(name); + return result; } /** - * Helper to set the signers of a class. This should be called after - * defining the class. + * Returns an Enumeration of all resources with a given name that can + * be found by this classloader and its parents. Certain classloaders + * (such as the URLClassLoader when given multiple jar files) can have + * multiple resources with the same name that come from multiple locations. + * It can also occur that a parent classloader offers a resource with a + * certain name and the child classloader also offers a resource with that + * same name. <code>getResource() only offers the first resource (of the + * parent) with a given name. This method lists all resources with the + * same name. The name should use '/' as path separators. * - * @param c the Class to set signers of - * @param signers the signers to set - * @since 1.1 - */ - protected final void setSigners(Class c, Object[] signers) + * <p>The Enumeration is created by first calling <code>getResources()</code> + * on the parent classloader and then calling <code>findResources()</code> + * on this classloader. + * + * @param name the resource name + * @return an enumaration of all resources found + * @throws IOException if I/O errors occur in the process + * @since 1.2 + */ + public final Enumeration getResources(String name) throws IOException { - /* - * Does currently nothing. FIXME. - */ + Enumeration parentResources; + if (parent == null) + parentResources = VMClassLoader.getResources(name); + else + parentResources = parent.getResources(name); + return new DoubleEnumeration(parentResources, findResources(name)); } /** - * 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 final synchronized Class findLoadedClass(String name) + * Called whenever all locations of a named resource are needed. + * It is called by <code>getResources()</code> after it has called + * <code>parent.getResources()</code>. The results are combined by + * the <code>getResources()</code> method. + * + * <p>The default implementation always returns an empty Enumeration. + * Subclasses should override it when they can provide an Enumeration of + * URLs (possibly just one element) to the named resource. + * The first URL of the Enumeration should be the same as the one + * returned by <code>findResource</code>. + * + * @param name the name of the resource to be found + * @return a possibly empty Enumeration of URLs to the named resource + * @throws IOException if I/O errors occur in the process + * @since 1.2 + */ + protected Enumeration findResources(String name) throws IOException { - return (Class) loadedClasses.get(name); + return EmptyEnumeration.getInstance(); } /** - * Get a resource using the system classloader. + * Called whenever a resource is needed that could not be provided by + * one of the parents of this classloader. It is called by + * <code>getResource()</code> after <code>parent.getResource()</code> + * couldn't provide the requested resource. * - * @param name the name of the resource relative to the system classloader - * @return an input stream for the resource, or null - * @since 1.1 + * <p>The default implementation always returns null. Subclasses should + * override this method when they can provide a way to return a URL + * to a named resource. + * + * @param name the name of the resource to be found + * @return a URL to the named resource or null when not found + * @since 1.2 */ - public static InputStream getSystemResourceAsStream(String name) { - return getSystemClassLoader().getResourceAsStream (name); + protected URL findResource(String name) + { + return null; } /** @@ -759,8 +625,9 @@ public abstract class ClassLoader * @return the URL to the resource * @since 1.1 */ - public static URL getSystemResource(String name) { - return getSystemClassLoader().getResource (name); + public static final URL getSystemResource(String name) + { + return systemClassLoader.getResource(name); } /** @@ -776,149 +643,221 @@ public abstract class ClassLoader */ public static Enumeration getSystemResources(String name) throws IOException { - return getSystemClassLoader().getResources(name); + return systemClassLoader.getResources(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.io.InputStream + * Get a resource as stream using this classloader or one of its parents. + * First calls <code>getResource()</code> and if that returns a URL to + * the resource then it calls and returns the InputStream given by + * <code>URL.openStream()</code>. + * + * <p>Subclasses should not override this method but should override + * <code>findResource()</code> which is called by this method. + * + * @param name the name of the resource relative to this classloader + * @return an InputStream to the resource, or null + * @since 1.1 */ - public InputStream getResourceAsStream(String name) + public InputStream getResourceAsStream(String name) { try { - URL res = getResource (name); - if (res == null) + URL url = getResource(name); + if (url == null) return null; - return res.openStream (); + return url.openStream(); } - catch (java.io.IOException x) + catch (IOException e) { - return null; + return null; } } - + /** - * Return an java.io.URL representing the resouce <code>name</code>. - * The default implementation just returns <code>null</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 + * Get a resource using the system classloader. + * + * @param name the name of the resource relative to the system classloader + * @return an input stream for the resource, or null + * @since 1.1 */ - public URL getResource (String name) + public static final InputStream getSystemResourceAsStream(String name) { - // The rules say search the parent class if non-null, - // otherwise search the built-in class loader (assumed to be - // the system ClassLoader). If not found, call - // findResource(). - URL result = null; - - ClassLoader delegate = parent; + try + { + URL url = getSystemResource(name); + if (url == null) + return null; + return url.openStream(); + } + catch (IOException e) + { + return null; + } + } - if (delegate == null) - delegate = getSystemClassLoader (); - - // Protect ourselves from looping. - if (this != delegate) - result = delegate.getResource (name); + /** + * Returns the system classloader. The system classloader (also called + * the application classloader) is the classloader that was used to + * load the application classes on the classpath (given by the system + * property <code>java.class.path</code>. This is set as the context + * class loader for a thread. The system property + * <code>java.system.class.loader</code>, if defined, is taken to be the + * name of the class to use as the system class loader, which must have + * a public constructor which takes a ClassLoader as a parent; otherwise this + * uses gnu.java.lang.SystemClassLoader. + * + * <p>Note that this is different from the bootstrap classloader that + * actually loads all the real "system" classes (the bootstrap classloader + * is the parent of the returned system classloader). + * + * <p>A security check will be performed for + * <code>RuntimePermission("getClassLoader")</code> if the calling class + * is not a parent of the system class loader. + * + * @return the system class loader + * @throws SecurityException if the security check fails + * @throws IllegalStateException if this is called recursively + * @throws Error if <code>java.system.class.loader</code> fails to load + * @since 1.2 + */ + public static ClassLoader getSystemClassLoader() + { + // Check if we may return the system classloader + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + { + Class c = VMSecurityManager.getClassContext()[1]; + ClassLoader cl = c.getClassLoader(); + if (cl != null && cl != systemClassLoader) + sm.checkPermission(new RuntimePermission("getClassLoader")); + } - if (result != null) - return result; - else - return findResource (name); + return systemClassLoader; } /** - * Called whenever a resource is needed that could not be provided by - * one of the parents of this classloader. It is called by - * <code>getResource()</code> after <code>parent.getResource()</code> - * couldn't provide the requested resource. + * Defines a new package and creates a Package object. The package should + * be defined before any class in the package is defined with + * <code>defineClass()</code>. The package should not yet be defined + * before in this classloader or in one of its parents (which means that + * <code>getPackage()</code> should return <code>null</code>). All + * parameters except the <code>name</code> of the package may be + * <code>null</code>. * - * <p>The default implementation always returns null. Subclasses should - * override this method when they can provide a way to return a URL - * to a named resource. + * <p>Subclasses should call this method from their <code>findClass()</code> + * implementation before calling <code>defineClass()</code> on a Class + * in a not yet defined Package (which can be checked by calling + * <code>getPackage()</code>). * - * @param name the name of the resource to be found - * @return a URL to the named resource or null when not found + * @param name the name of the Package + * @param specTitle the name of the specification + * @param specVendor the name of the specification designer + * @param specVersion the version of this specification + * @param implTitle the name of the implementation + * @param implVendor the vendor that wrote this implementation + * @param implVersion the version of this implementation + * @param sealed if sealed the origin of the package classes + * @return the Package object for the specified package + * @throws IllegalArgumentException if the package name is null or it + * was already defined by this classloader or one of its parents + * @see Package * @since 1.2 */ - protected URL findResource (String name) + protected Package definePackage(String name, String specTitle, + String specVendor, String specVersion, + String implTitle, String implVendor, + String implVersion, URL sealed) { - // Default to returning null. Derived classes implement this. - return null; + if (getPackage(name) != null) + throw new IllegalArgumentException("Package " + name + + " already defined"); + Package p = new Package(name, specTitle, specVendor, specVersion, + implTitle, implVendor, implVersion, sealed); + synchronized (definedPackages) + { + definedPackages.put(name, p); + } + return p; } /** - * Returns an Enumeration of all resources with a given name that can - * be found by this classloader and its parents. Certain classloaders - * (such as the URLClassLoader when given multiple jar files) can have - * multiple resources with the same name that come from multiple locations. - * It can also occur that a parent classloader offers a resource with a - * certain name and the child classloader also offers a resource with that - * same name. <code>getResource() only offers the first resource (of the - * parent) with a given name. This method lists all resources with the - * same name. The name should use '/' as path separators. - * - * <p>The Enumeration is created by first calling <code>getResources()</code> - * on the parent classloader and then calling <code>findResources()</code> - * on this classloader. + * Returns the Package object for the requested package name. It returns + * null when the package is not defined by this classloader or one of its + * parents. * - * @param name the resource name - * @return an enumaration of all resources found - * @throws IOException if I/O errors occur in the process + * @param name the package name to find + * @return the package, if defined * @since 1.2 */ - public final Enumeration getResources(String name) throws IOException + protected Package getPackage(String name) { - // The rules say search the parent class if non-null, - // otherwise search the built-in class loader (assumed to be - // the system ClassLoader). If not found, call - // findResource(). - Enumeration result = null; + Package p; + if (parent == null) + p = VMClassLoader.getPackage(name); + else + p = parent.getPackage(name); - ClassLoader delegate = parent; + if (p == null) + { + synchronized (definedPackages) + { + p = (Package) definedPackages.get(name); + } + } + return p; + } - if (delegate == null) - delegate = getSystemClassLoader (); - - // Protect ourselves from looping. - if (this != delegate) - result = delegate.getResources (name); + /** + * Returns all Package objects defined by this classloader and its parents. + * + * @return an array of all defined packages + * @since 1.2 + */ + protected Package[] getPackages() + { + // Get all our packages. + Package[] packages; + synchronized(definedPackages) + { + packages = new Package[definedPackages.size()]; + definedPackages.values().toArray(packages); + } - if (result != null) - return result; + // If we have a parent get all packages defined by our parents. + Package[] parentPackages; + if (parent == null) + parentPackages = VMClassLoader.getPackages(); else - return findResources (name); + parentPackages = parent.getPackages(); + + Package[] allPackages = new Package[parentPackages.length + + packages.length]; + System.arraycopy(parentPackages, 0, allPackages, 0, + parentPackages.length); + System.arraycopy(packages, 0, allPackages, parentPackages.length, + packages.length); + return allPackages; } /** - * Called whenever all locations of a named resource are needed. - * It is called by <code>getResources()</code> after it has called - * <code>parent.getResources()</code>. The results are combined by - * the <code>getResources()</code> method. - * - * <p>The default implementation always returns an empty Enumeration. - * Subclasses should override it when they can provide an Enumeration of - * URLs (possibly just one element) to the named resource. - * The first URL of the Enumeration should be the same as the one - * returned by <code>findResource</code>. + * Called by <code>Runtime.loadLibrary()</code> to get an absolute path + * to a (system specific) library that was requested by a class loaded + * by this classloader. The default implementation returns + * <code>null</code>. It should be implemented by subclasses when they + * have a way to find the absolute path to a library. If this method + * returns null the library is searched for in the default locations + * (the directories listed in the <code>java.library.path</code> system + * property). * - * @param name the name of the resource to be found - * @return a possibly empty Enumeration of URLs to the named resource - * @throws IOException if I/O errors occur in the process + * @param name the (system specific) name of the requested library + * @return the full pathname to the requested library, or null + * @see Runtime#loadLibrary() * @since 1.2 */ - protected Enumeration findResources(String name) throws IOException + protected String findLibrary(String name) { - return Collections.enumeration(Collections.EMPTY_LIST); + return null; } /** @@ -935,7 +874,7 @@ public abstract class ClassLoader { defaultAssertionStatus = enabled; } - + /** * Set the default assertion status for packages, used unless overridden * by a class request. This default also covers subpackages, unless they diff --git a/libjava/java/lang/VMClassLoader.java b/libjava/java/lang/VMClassLoader.java index 11b75548e53..b46b545aeed 100644 --- a/libjava/java/lang/VMClassLoader.java +++ b/libjava/java/lang/VMClassLoader.java @@ -1,66 +1,237 @@ -/* - * java.lang.ClassLoader: part of the Java Class Libraries project. - * Copyright (C) 1998, 2001, 2002 Free Software Foundation - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ +/* VMClassLoader.java -- Reference implementation of native interface + required by ClassLoader + Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ package java.lang; -import java.util.*; +import java.security.ProtectionDomain; +import java.net.URL; +import java.io.IOException; +import java.util.Enumeration; +import java.util.Map; +import java.util.HashMap; +import java.lang.reflect.Constructor; +import java.security.AllPermission; +import java.security.Permission; +import java.security.Permissions; +import java.security.ProtectionDomain; + +import gnu.java.util.EmptyEnumeration; /** * java.lang.VMClassLoader is a package-private helper for VMs to implement * on behalf of java.lang.ClassLoader. * * @author John Keiser - * @version 1.1.0, Sep 22 1998 - * @since CP1.1 + * @author Mark Wielaard <mark@klomp.org> + * @author Eric Blake <ebb9@email.byu.edu> */ +final class VMClassLoader +{ + // Protection Domain definitions + // FIXME: should there be a special protection domain used for native code? + + // The permission required to check what a classes protection domain is. + static final Permission protectionDomainPermission + = new RuntimePermission("getProtectionDomain"); + // The protection domain returned if we cannot determine it. + static ProtectionDomain unknownProtectionDomain; + + static + { + Permissions permissions = new Permissions(); + permissions.add(new AllPermission()); + unknownProtectionDomain = new ProtectionDomain(null, permissions); + } + + /** + * Helper to define a class using a string of bytes. This assumes that + * the security checks have already been performed, if necessary. + * + * <strong>For backward compatibility, this just ignores the protection + * domain; that is the wrong behavior, and you should directly implement + * this method natively if you can.</strong> + * + * @param name the name to give the class, or null if unknown + * @param data the data representing the classfile, in classfile format + * @param offset the offset into the data where the classfile starts + * @param len the length of the classfile data in the array + * @param pd the protection domain + * @return the class that was defined + * @throws ClassFormatError if data is not in proper classfile format + */ + static final native Class defineClass(ClassLoader cl, String name, + byte[] data, int offset, int len, + ProtectionDomain pd) + throws ClassFormatError; + + static final native void linkClass0 (Class klass); + static final native void markClassErrorState0 (Class klass); + + /** + * Helper to resolve all references to other classes from this class. + * + * @param c the class to resolve + */ + static final void resolveClass(Class clazz) + { + synchronized (clazz) + { + try + { + linkClass0 (clazz); + } + catch (Throwable x) + { + markClassErrorState0 (clazz); + + LinkageError e; + if (x instanceof LinkageError) + e = (LinkageError) x; + else if (x instanceof ClassNotFoundException) + { + e = new NoClassDefFoundError("while resolving class: " + + clazz.getName()); + e.initCause (x); + } + else + { + e = new LinkageError ("unexpected exception during linking: " + + clazz.getName()); + e.initCause (x); + } + throw e; + } + } + } + + /** + * Helper to load a class from the bootstrap class loader. + * + * In libgcj, this does nothing, as the default system loader knows + * how to find classes that have been linked in. + * + * @param name the class name to load + * @param resolve whether to resolve it + * @return the class, loaded by the bootstrap classloader or null + * if the class wasn't found. Returning null is equivalent to throwing + * a ClassNotFoundException (but a possible performance optimization). + */ + static final Class loadClass(String name, boolean resolve) + throws ClassNotFoundException + { + return null; + } -class VMClassLoader { - - /** - * Helper to define a class using a string of bytes. - * - * @param name the name to give the class. null if unknown. - * @param data the data representing the classfile, in classfile format. - * @param offset the offset into the data where the classfile starts. - * @param len the length of the classfile data in the array. - * @return the class that was defined. - * @exception ClassFormatError if the byte array is not in proper classfile format. - */ - final static native Class defineClass(ClassLoader cl, String name, - byte[] data, int offset, int len) - throws ClassFormatError; - - /** - * Helper to resolve all references to other classes from this class. - * @param c the class to resolve. - */ - // Not yet needed for libgcj. - // final static native void resolveClass(Class c); - - /** - * Helper for java.lang.Integer, Byte, etc. to get the TYPE class - * at initialization time. - * - * @param type code for the primitive type. - */ - static native Class getPrimitiveClass(char type); + /** + * Helper to load a resource from the bootstrap class loader. + * + * In libgcj, this does nothing, as the default system loader knows + * how to find resources that have been linked in. + * + * @param name the resource to find + * @return the URL to the resource + */ + static URL getResource(String name) + { + return null; + } + + /** + * Helper to get a list of resources from the bootstrap class loader. + * + * In libgcj, this does nothing, as the default system loader knows + * how to find resources that have been linked in. + * + * @param name the resource to find + * @return an enumeration of resources + * @throws IOException if one occurs + */ + static Enumeration getResources(String name) throws IOException + { + return EmptyEnumeration.getInstance(); + } + + /** + * Helper to get a package from the bootstrap class loader. The default + * implementation of returning null may be adequate, or you may decide + * that this needs some native help. + * + * @param name the name to find + * @return the named package, if it exists + */ + static Package getPackage(String name) + { + return null; + } + + /** + * Helper to get all packages from the bootstrap class loader. The default + * implementation of returning an empty array may be adequate, or you may + * decide that this needs some native help. + * + * @return all named packages, if any exist + */ + static Package[] getPackages() + { + return new Package[0]; + } + + /** + * Helper for java.lang.Integer, Byte, etc to get the TYPE class + * at initialization time. The type code is one of the chars that + * represents the primitive type as in JNI. + * + * <ul> + * <li>'Z' - boolean</li> + * <li>'B' - byte</li> + * <li>'C' - char</li> + * <li>'D' - double</li> + * <li>'F' - float</li> + * <li>'I' - int</li> + * <li>'J' - long</li> + * <li>'S' - short</li> + * <li>'V' - void</li> + * </ul> + * + * @param type the primitive type + * @return a "bogus" class representing the primitive type + */ + static final native Class getPrimitiveClass(char type); /** * The system default for assertion status. This is used for all system @@ -104,4 +275,34 @@ class VMClassLoader { { return new HashMap(); } + + static native ClassLoader getSystemClassLoaderInternal(); + + static ClassLoader getSystemClassLoader() + { + // This method is called as the initialization of systemClassLoader, + // so if there is a null value, this is the first call and we must check + // for java.system.class.loader. + String loader = System.getProperty("java.system.class.loader"); + ClassLoader default_sys = getSystemClassLoaderInternal(); + if (loader != null) + { + try + { + Class load_class = Class.forName(loader, true, default_sys); + Constructor c + = load_class.getConstructor(new Class[] { ClassLoader.class }); + default_sys + = (ClassLoader) c.newInstance(new Object[] { default_sys }); + } + catch (Exception e) + { + System.err.println("Requested system classloader " + + loader + " failed, using " + + "gnu.gcj.runtime.VMClassLoader"); + e.printStackTrace(); + } + } + return default_sys; + } } diff --git a/libjava/java/lang/natClass.cc b/libjava/java/lang/natClass.cc index 4b0858225df..551a5312fe5 100644 --- a/libjava/java/lang/natClass.cc +++ b/libjava/java/lang/natClass.cc @@ -48,6 +48,7 @@ details. */ #include <java/lang/System.h> #include <java/lang/SecurityManager.h> #include <java/lang/StringBuffer.h> +#include <java/lang/VMClassLoader.h> #include <gnu/gcj/runtime/StackTrace.h> #include <gcj/method.h> #include <gnu/gcj/runtime/MethodRef.h> @@ -758,7 +759,7 @@ java::lang::Class::initializeClass (void) { // this can throw exceptions, so exit the monitor as a precaution. _Jv_MonitorExit (this); - java::lang::ClassLoader::resolveClass0 (this); + java::lang::VMClassLoader::resolveClass (this); _Jv_MonitorEnter (this); } else diff --git a/libjava/java/lang/natClassLoader.cc b/libjava/java/lang/natClassLoader.cc index 7ca537c365f..bfd1f095d9e 100644 --- a/libjava/java/lang/natClassLoader.cc +++ b/libjava/java/lang/natClassLoader.cc @@ -1,6 +1,6 @@ // natClassLoader.cc - Implementation of java.lang.ClassLoader native methods. -/* Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation +/* Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation This file is part of libgcj. @@ -44,11 +44,12 @@ details. */ /////////// java.lang.ClassLoader native methods //////////// java::lang::Class * -java::lang::ClassLoader::defineClass0 (jstring name, - jbyteArray data, - jint offset, - jint length, - java::security::ProtectionDomain *pd) +java::lang::VMClassLoader::defineClass (java::lang::ClassLoader *loader, + jstring name, + jbyteArray data, + jint offset, + jint length, + java::security::ProtectionDomain *pd) { #ifdef INTERPRETER jclass klass; @@ -62,8 +63,8 @@ java::lang::ClassLoader::defineClass0 (jstring name, // Record the defining loader. For the system class loader, we // record NULL. - if (this != java::lang::ClassLoader::getSystemClassLoader()) - klass->loader = this; + if (loader != java::lang::ClassLoader::getSystemClassLoader()) + klass->loader = loader; if (name != 0) { @@ -105,6 +106,36 @@ java::lang::ClassLoader::defineClass0 (jstring name, #endif } +// Finish linking a class. Only called from ClassLoader::resolveClass. +void +java::lang::VMClassLoader::linkClass0 (java::lang::Class *klass) +{ + _Jv_WaitForState (klass, JV_STATE_LINKED); +} + +void +java::lang::VMClassLoader::markClassErrorState0 (java::lang::Class *klass) +{ + klass->state = JV_STATE_ERROR; + klass->notifyAll (); +} + +java::lang::ClassLoader * +java::lang::VMClassLoader::getSystemClassLoaderInternal() +{ + _Jv_InitClass (&gnu::gcj::runtime::VMClassLoader::class$); + return gnu::gcj::runtime::VMClassLoader::instance; +} + +jclass +java::lang::VMClassLoader::getPrimitiveClass (jchar type) +{ + char sig[2]; + sig[0] = (char) type; + sig[1] = '\0'; + return _Jv_FindClassFromSignature (sig, NULL); +} + void _Jv_WaitForState (jclass klass, int state) { @@ -141,39 +172,6 @@ _Jv_WaitForState (jclass klass, int state) throw new java::lang::LinkageError; } -// Finish linking a class. Only called from ClassLoader::resolveClass. -void -java::lang::ClassLoader::linkClass0 (java::lang::Class *klass) -{ - _Jv_WaitForState (klass, JV_STATE_LINKED); -} - -void -java::lang::ClassLoader::markClassErrorState0 (java::lang::Class *klass) -{ - klass->state = JV_STATE_ERROR; - klass->notifyAll (); -} - -jclass -java::lang::VMClassLoader::defineClass (java::lang::ClassLoader *cl, - jstring name, - jbyteArray data, - jint offset, - jint length) -{ - return cl->defineClass (name, data, offset, length); -} - -jclass -java::lang::VMClassLoader::getPrimitiveClass (jchar type) -{ - char sig[2]; - sig[0] = (char) type; - sig[1] = '\0'; - return _Jv_FindClassFromSignature (sig, NULL); -} - typedef unsigned int uaddr __attribute__ ((mode (pointer))); /** This function does class-preparation for compiled classes. @@ -281,7 +279,7 @@ _Jv_PrepareCompiledClass (jclass klass) // The set of initiating class loaders are used to ensure // safety of linking, and is maintained in the hash table // "initiated_classes". A defining classloader is by definition also -// initiating, so we only store classes in this table, if they have more +// initiating, so we only store classes in this table if they have more // than one class loader associated. // diff --git a/libjava/java/lang/reflect/Proxy.java b/libjava/java/lang/reflect/Proxy.java index 1b38a483842..9009bc8031b 100644 --- a/libjava/java/lang/reflect/Proxy.java +++ b/libjava/java/lang/reflect/Proxy.java @@ -1335,17 +1335,10 @@ public class Proxy implements Serializable { // XXX Do we require more native support here? - // XXX Security hole - it is possible for another thread to grab the - // VMClassLoader.defineClass Method object, and abuse it while we - // have temporarily made it accessible. Do we need to add some - // synchronization lock to prevent user reflection while we use it? - - // XXX This is waiting on VM support for protection domains. - Class vmClassLoader = Class.forName("java.lang.VMClassLoader"); Class[] types = {ClassLoader.class, String.class, byte[].class, int.class, int.class, - /* ProtectionDomain.class */ }; + ProtectionDomain.class }; Method m = vmClassLoader.getDeclaredMethod("defineClass", types); // Bypass the security check of setAccessible(true), since this @@ -1354,7 +1347,7 @@ public class Proxy implements Serializable m.flag = true; Object[] args = {loader, qualName, bytecode, new Integer(0), new Integer(bytecode.length), - /* Object.class.getProtectionDomain() */ }; + Object.class.getProtectionDomain() }; Class clazz = (Class) m.invoke(null, args); m.flag = false; diff --git a/libjava/resolve.cc b/libjava/resolve.cc index d79affea9eb..ce1af8d2586 100644 --- a/libjava/resolve.cc +++ b/libjava/resolve.cc @@ -32,6 +32,7 @@ details. */ #include <java/lang/AbstractMethodError.h> #include <java/lang/NoClassDefFoundError.h> #include <java/lang/IncompatibleClassChangeError.h> +#include <java/lang/VMClassLoader.h> #include <java/lang/reflect/Modifier.h> using namespace gcj; @@ -435,7 +436,7 @@ _Jv_PrepareClass(jclass klass) // resolved. if (klass->superclass) - java::lang::ClassLoader::resolveClass0 (klass->superclass); + java::lang::VMClassLoader::resolveClass (klass->superclass); _Jv_InterpClass *clz = (_Jv_InterpClass*)klass; |