aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libjava/ChangeLog23
-rw-r--r--libjava/gcj/javaprims.h35
-rw-r--r--libjava/gnu/gcj/runtime/VMClassLoader.java2
-rw-r--r--libjava/java/lang/Class.h1
-rw-r--r--libjava/java/lang/Class.java4
-rw-r--r--libjava/java/lang/ClassLoader.java1101
-rw-r--r--libjava/java/lang/VMClassLoader.java305
-rw-r--r--libjava/java/lang/natClass.cc3
-rw-r--r--libjava/java/lang/natClassLoader.cc82
-rw-r--r--libjava/java/lang/reflect/Proxy.java11
-rw-r--r--libjava/resolve.cc3
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;