This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
Backport of my recent patches to 3.0 branch
- To: java-patches at gcc dot gnu dot org
- Subject: Backport of my recent patches to 3.0 branch
- From: Bryce McKinlay <bryce at waitaki dot otago dot ac dot nz>
- Date: Mon, 07 May 2001 02:09:16 +1200
This patch backports some parts of my recent patches to the 3.0 branch.
It includes the Class.forName()/ClassLoader fixes/cleanups,
serialization fixes, and the vtable-setting fix/cleanup. I'm checking it
in.
regards
[ bryce ]
2001-05-06 Bryce McKinlay <bryce@waitaki.otago.ac.nz>
* java/lang/Class.h (_Jv_Self): New union type.
(Class): Manipulate vtable pointer via _Jv_Self union. Thanks to
Jeff Sturm and Fergus Henderson.
2001-05-06 Bryce McKinlay <bryce@waitaki.otago.ac.nz>
Fix PR libgcj/2237:
* java/io/ObjectStreamClass.java (setClass): Calculate
serialVersionUID for local class and compare it against the UID
from the Object Stream. Throw InvalidClassException upon mismatch.
(setUID): Renamed to...
(getClassUID): this. Return the calculated class UID rather than
setting uid field directly.
(getDefinedSUID): Removed.
* java/io/ObjectInputStream.java (resolveClass): Use the
three-argument Class.forName().
* java/io/InvalidClassException.java (toString): Don't include
classname in result if it is null.
2001-05-06 Bryce McKinlay <bryce@waitaki.otago.ac.nz>
* java/lang/Class.h (forName): Add initialize parameter. Fixes
declaration to comply with JDK spec.
* java/lang/natClass.cc (forName): Correct declaration of the three-arg
variant. Honour "initialize" flag.
* java/lang/Class.java: Fix forName() declaration.
* java/lang/ClassLoader.java (getParent): Now final.
(findSystemClass): Now final.
(getSystemResourceAsStream): Remove redundant "final" modifier.
(getSystemResource): Remove redundant "final" modifier.
(getResources): Now final.
(getSystemClassLoader): Now non-native.
* java/util/ResourceBundle.java (tryGetSomeBundle): Use the correct
arguments for Class.forName().
* gnu/gcj/runtime/VMClassLoader.java (getVMClassLoader): Removed.
(instance): Static initialize singleton.
(findClass): Override this, not findSystemClass.
* java/lang/natClassLoader.cc (findClass): Renamed from
findSystemClass. Call the interpreter via URLClassLoader.findClass if
loading class via dlopen fails.
Index: java/lang/Class.h
===================================================================
RCS file: /cvs/gcc/egcs/libjava/java/lang/Class.h,v
retrieving revision 1.31
diff -u -r1.31 Class.h
--- Class.h 2001/01/17 10:22:32 1.31
+++ Class.h 2001/05/06 14:01:47
@@ -98,6 +98,13 @@
jshort count;
};
+// Used for vtable pointer manipulation.
+union _Jv_Self
+{
+ char *vtable_ptr;
+ jclass self;
+};
+
#define JV_PRIMITIVE_VTABLE ((_Jv_VTable *) -1)
#define JV_CLASS(Obj) ((jclass) (*(_Jv_VTable **) Obj)->clas)
@@ -105,7 +112,8 @@
class java::lang::Class : public java::lang::Object
{
public:
- static jclass forName (jstring className, java::lang::ClassLoader *loader);
+ static jclass forName (jstring className, jboolean initialize,
+ java::lang::ClassLoader *loader);
static jclass forName (jstring className);
JArray<jclass> *getClasses (void);
@@ -208,9 +216,8 @@
// C++ ctors set the vtbl pointer to point at an offset inside the vtable
// object. That doesn't work for Java, so this hack adjusts it back.
- void *p = ((void **)this)[0];
- ((void **)this)[0] = (void *)((char *)p-2*sizeof (void *));
-
+ ((_Jv_Self *)this)->vtable_ptr -= 2 * sizeof (void *);
+
// We must initialize every field of the class. We do this in the
// same order they are declared in Class.h, except for fields that
// are initialized to NULL.
Index: java/lang/natClass.cc
===================================================================
RCS file: /cvs/gcc/egcs/libjava/java/lang/natClass.cc,v
retrieving revision 1.36.2.2
diff -u -r1.36.2.2 natClass.cc
--- natClass.cc 2001/03/24 00:27:41 1.36.2.2
+++ natClass.cc 2001/05/06 14:01:48
@@ -72,7 +72,8 @@
jclass
-java::lang::Class::forName (jstring className, java::lang::ClassLoader *loader)
+java::lang::Class::forName (jstring className, jboolean initialize,
+ java::lang::ClassLoader *loader)
{
if (! className)
JvThrow (new java::lang::NullPointerException);
@@ -90,10 +91,11 @@
? _Jv_FindClassFromSignature (name->data, loader)
: _Jv_FindClass (name, loader));
- if (klass)
+ if (klass == NULL)
+ throw new java::lang::ClassNotFoundException (className);
+
+ if (initialize)
_Jv_InitClass (klass);
- else
- JvThrow (new java::lang::ClassNotFoundException (className));
return klass;
}
@@ -102,7 +104,7 @@
java::lang::Class::forName (jstring className)
{
// FIXME: should use class loader from calling method.
- return forName (className, NULL);
+ return forName (className, true, NULL);
}
java::lang::reflect::Constructor *
Index: java/lang/Class.java
===================================================================
RCS file: /cvs/gcc/egcs/libjava/java/lang/Class.java,v
retrieving revision 1.10
diff -u -r1.10 Class.java
--- Class.java 2000/11/26 03:58:55 1.10
+++ Class.java 2001/05/06 14:01:48
@@ -30,7 +30,9 @@
{
public static native Class forName (String className)
throws ClassNotFoundException;
- public static native Class forName (String className, ClassLoader loader)
+ /** @since 1.2 */
+ public static native Class forName (String className, boolean initialize,
+ ClassLoader loader)
throws ClassNotFoundException;
public native Class[] getClasses ();
public native ClassLoader getClassLoader ();
Index: java/lang/ClassLoader.java
===================================================================
RCS file: /cvs/gcc/egcs/libjava/java/lang/ClassLoader.java,v
retrieving revision 1.11
diff -u -r1.11 ClassLoader.java
--- ClassLoader.java 2000/11/27 04:07:48 1.11
+++ ClassLoader.java 2001/05/06 14:01:48
@@ -1,6 +1,6 @@
// ClassLoader.java - Define policies for loading Java classes.
-/* Copyright (C) 1998, 1999, 2000 Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation
This file is part of libgcj.
@@ -25,18 +25,23 @@
* @author Kresten Krab Thorup
*/
-public abstract class ClassLoader {
-
+public abstract class ClassLoader
+{
static private ClassLoader system;
private ClassLoader parent;
- public ClassLoader getParent ()
+ public final ClassLoader getParent ()
{
/* FIXME: security */
return parent;
}
-
- public static native ClassLoader getSystemClassLoader ();
+
+ public static ClassLoader getSystemClassLoader ()
+ {
+ if (system == null)
+ system = gnu.gcj.runtime.VMClassLoader.instance;
+ return system;
+ }
/**
* Creates a <code>ClassLoader</code> with no parent.
@@ -55,6 +60,7 @@
* <code>checkCreateClassLoader</code> on the current
* security manager.
* @exception java.lang.SecurityException if not allowed
+ * @since 1.2
*/
protected ClassLoader(ClassLoader parent)
{
@@ -71,12 +77,12 @@
* @see ClassLoader#loadClass(String,boolean)
* @exception java.lang.ClassNotFoundException
*/
- public Class loadClass(String name)
- throws java.lang.ClassNotFoundException, java.lang.LinkageError
+ 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)
@@ -96,7 +102,7 @@
* @deprecated
*/
protected Class loadClass(String name, boolean link)
- throws java.lang.ClassNotFoundException, java.lang.LinkageError
+ throws java.lang.ClassNotFoundException
{
Class c = findLoadedClass (name);
@@ -106,7 +112,7 @@
if (parent != null)
return parent.loadClass (name, link);
else
- c = findSystemClass (name);
+ c = system.findClass (name);
} catch (ClassNotFoundException ex) {
/* ignore, we'll try findClass */;
}
@@ -130,6 +136,7 @@
* @param name Name of the class to find.
* @return The class found.
* @exception java.lang.ClassNotFoundException
+ * @since 1.2
*/
protected Class findClass (String name)
throws ClassNotFoundException
@@ -201,7 +208,7 @@
throw new java.lang.LinkageError ("class "
+ name
+ " already loaded");
-
+
try {
// Since we're calling into native code here,
// we better make sure that any generated
@@ -232,7 +239,6 @@
int len)
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
@@ -262,13 +268,11 @@
* @exception java.lang.LinkageError
*/
protected final void resolveClass(Class clazz)
- throws java.lang.LinkageError
{
resolveClass0(clazz);
}
static void resolveClass0(Class clazz)
- throws java.lang.LinkageError
{
synchronized (clazz)
{
@@ -288,15 +292,13 @@
/** Internal method. Calls _Jv_PrepareClass and
* _Jv_PrepareCompiledClass. This is only called from resolveClass. */
- private static native void linkClass0(Class clazz)
- throws java.lang.LinkageError;
+ 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);
-
/**
* Returns a class found in a system-specific way, typically
* via the <code>java.class.path</code> system property. Loads the
@@ -307,14 +309,14 @@
* @exception java.lang.LinkageError
* @exception java.lang.ClassNotFoundException
*/
- protected Class findSystemClass(String name)
- throws java.lang.ClassNotFoundException, java.lang.LinkageError
+ protected final Class findSystemClass(String name)
+ throws java.lang.ClassNotFoundException
{
return getSystemClassLoader ().loadClass (name);
}
/*
- * Does currently nothing.
+ * Does currently nothing. FIXME.
*/
protected final void setSigners(Class claz, Object[] signers) {
/* claz.setSigners (signers); */
@@ -328,13 +330,13 @@
* @param name class to find.
* @return the class loaded, or null.
*/
- protected native Class findLoadedClass(String name);
+ protected final native Class findLoadedClass(String name);
- public static final InputStream getSystemResourceAsStream(String name) {
+ public static InputStream getSystemResourceAsStream(String name) {
return getSystemClassLoader().getResourceAsStream (name);
}
- public static final URL getSystemResource(String name) {
+ public static URL getSystemResource(String name) {
return getSystemClassLoader().getResource (name);
}
@@ -397,7 +399,7 @@
return null;
}
- public Enumeration getResources (String name) throws IOException
+ public final Enumeration getResources (String name) throws IOException
{
// The rules say search the parent class if non-null,
// otherwise search the built-in class loader (assumed to be
Index: java/lang/natClassLoader.cc
===================================================================
RCS file: /cvs/gcc/egcs/libjava/java/lang/natClassLoader.cc,v
retrieving revision 1.28.4.1
diff -u -r1.28.4.1 natClassLoader.cc
--- natClassLoader.cc 2001/03/03 07:28:00 1.28.4.1
+++ natClassLoader.cc 2001/05/06 14:01:48
@@ -48,15 +48,6 @@
/////////// java.lang.ClassLoader native methods ////////////
-java::lang::ClassLoader *
-java::lang::ClassLoader::getSystemClassLoader (void)
-{
- JvSynchronize sync (&ClassLoaderClass);
- if (! system)
- system = gnu::gcj::runtime::VMClassLoader::getVMClassLoader ();
- return system;
-}
-
java::lang::Class *
java::lang::ClassLoader::defineClass0 (jstring name,
jbyteArray data,
@@ -178,11 +169,10 @@
klass->notifyAll ();
}
-
-/** this is the only native method in VMClassLoader, so
- we define it here. */
+// This is the findClass() implementation for the System classloader. It is
+// the only native method in VMClassLoader, so we define it here.
jclass
-gnu::gcj::runtime::VMClassLoader::findSystemClass (jstring name)
+gnu::gcj::runtime::VMClassLoader::findClass (jstring name)
{
_Jv_Utf8Const *name_u = _Jv_makeUtf8Const (name);
jclass klass = _Jv_FindClassInCache (name_u, 0);
@@ -211,6 +201,12 @@
klass = _Jv_FindClassInCache (name_u, 0);
}
}
+
+ // Now try loading using the interpreter.
+ if (! klass)
+ {
+ klass = java::net::URLClassLoader::findClass (name);
+ }
return klass;
}
Index: java/io/ObjectStreamClass.java
===================================================================
RCS file: /cvs/gcc/egcs/libjava/java/io/ObjectStreamClass.java,v
retrieving revision 1.6.4.1
diff -u -r1.6.4.1 ObjectStreamClass.java
--- ObjectStreamClass.java 2001/03/09 01:34:40 1.6.4.1
+++ ObjectStreamClass.java 2001/05/06 14:01:48
@@ -246,13 +246,27 @@
this.fields = fields;
}
-
- void setClass (Class clazz)
+ void setClass (Class cl) throws InvalidClassException
{
- this.clazz = clazz;
+ this.clazz = cl;
+ long class_uid = getClassUID (cl);
+ if (uid == 0)
+ {
+ uid = class_uid;
+ return;
+ }
+
+ // Check that the actual UID of the resolved class matches the UID from
+ // the stream.
+ if (uid != class_uid)
+ {
+ String msg = cl +
+ ": Local class not compatible: stream serialVersionUID="
+ + uid + ", local serialVersionUID=" + class_uid;
+ throw new InvalidClassException (msg);
+ }
}
-
void setSuperclass (ObjectStreamClass osc)
{
superClass = osc;
@@ -308,7 +322,7 @@
name = cl.getName ();
setFlags (cl);
setFields (cl);
- setUID (cl);
+ uid = getClassUID (cl);
superClass = lookup (cl.getSuperclass ());
}
@@ -396,24 +410,24 @@
calculateOffsets ();
}
- // Sets uid to be serial version UID defined by class, or if that
+ // Returns the serial version UID defined by class, or if that
// isn't present, calculates value of serial version UID.
- private void setUID (Class cl)
+ private long getClassUID (Class cl)
{
try
{
Field suid = cl.getDeclaredField ("serialVersionUID");
int modifiers = suid.getModifiers ();
- if (Modifier.isStatic (modifiers)
- && Modifier.isFinal (modifiers))
- {
- uid = getDefinedSUID (cl);
- return;
- }
+ if (Modifier.isStatic (modifiers) && Modifier.isFinal (modifiers))
+ return suid.getLong (null);
}
catch (NoSuchFieldException ignore)
- {}
+ {
+ }
+ catch (IllegalAccessException ignore)
+ {
+ }
// cl didn't define serialVersionUID, so we have to compute it
try
@@ -534,7 +548,7 @@
for (int i=0; i < len; i++)
result += (long)(sha[i] & 0xFF) << (8 * i);
- uid = result;
+ return result;
}
catch (NoSuchAlgorithmException e)
{
@@ -545,31 +559,6 @@
{
throw new RuntimeException (ioe.getMessage ());
}
- }
-
-
- // Returns the value of CLAZZ's final static long field named
- // `serialVersionUID'.
- private long getDefinedSUID (Class clazz)
- {
- long l = 0;
- try
- {
- // Use getDeclaredField rather than getField, since serialVersionUID
- // may not be public AND we only want the serialVersionUID of this
- // class, not a superclass or interface.
- Field f = clazz.getDeclaredField ("serialVersionUID");
- l = f.getLong (null);
- }
- catch (java.lang.NoSuchFieldException e)
- {
- }
-
- catch (java.lang.IllegalAccessException e)
- {
- }
-
- return l;
}
// Returns the value of CLAZZ's private static final field named
Index: java/io/ObjectInputStream.java
===================================================================
RCS file: /cvs/gcc/egcs/libjava/java/io/ObjectInputStream.java,v
retrieving revision 1.6.4.1
diff -u -r1.6.4.1 ObjectInputStream.java
--- ObjectInputStream.java 2001/02/17 01:06:44 1.6.4.1
+++ ObjectInputStream.java 2001/05/06 14:01:48
@@ -199,8 +199,8 @@
(class_name));
}
- setBlockDataMode (true);
- osc.setClass (resolveClass (osc));
+ Class cl = resolveClass (osc);
+ osc.setClass (cl);
setBlockDataMode (false);
if (this.realInputStream.readByte () != TC_ENDBLOCKDATA)
@@ -487,27 +487,15 @@
protected Class resolveClass (ObjectStreamClass osc)
throws ClassNotFoundException, IOException
{
-// DEBUGln ("Resolving " + osc);
-
SecurityManager sm = System.getSecurityManager ();
-
- if (sm == null)
- sm = new SecurityManager () {};
+ // FIXME: currentClassLoader doesn't yet do anything useful. We need
+ // to call forName() with the classloader of the class which called
+ // readObject(). See SecurityManager.getClassContext().
ClassLoader cl = currentClassLoader (sm);
- if (cl == null)
- {
-// DEBUGln ("No class loader found");
- return Class.forName (osc.getName ());
- }
- else
- {
-// DEBUGln ("Using " + cl);
- return cl.loadClass (osc.getName ());
- }
+ return Class.forName (osc.getName (), true, cl);
}
-
/**
Allows subclasses to resolve objects that are read from the
Index: java/io/InvalidClassException.java
===================================================================
RCS file: /cvs/gcc/egcs/libjava/java/io/InvalidClassException.java,v
retrieving revision 1.1
diff -u -r1.1 InvalidClassException.java
--- InvalidClassException.java 2000/05/19 17:55:31 1.1
+++ InvalidClassException.java 2001/05/06 14:01:48
@@ -44,67 +44,44 @@
*/
public class InvalidClassException extends ObjectStreamException
{
-
-/*
- * Instance Variables
- */
-
-/**
- * The name of the class which encountered the error.
- */
-public String classname;
-
-/*************************************************************************/
-
-/*
- * Constructors
- */
-
-/**
- * Create a new InvalidClassException with a descriptive error message String
- *
- * @param message The descriptive error message
- */
-public
-InvalidClassException(String message)
-{
- super(message);
+ /**
+ * The name of the class which encountered the error.
+ */
+ public String classname;
+
+ /**
+ * Create a new InvalidClassException with a descriptive error message String
+ *
+ * @param message The descriptive error message
+ */
+ public InvalidClassException(String message)
+ {
+ super(message);
+ }
+
+ /**
+ * Create a new InvalidClassException with a descriptive error message
+ * String, and the name of the class that caused the problem.
+ *
+ * @param classname The number of bytes tranferred before the interruption
+ * @param message The descriptive error message
+ */
+ public InvalidClassException(String classname, String message)
+ {
+ super(message);
+ this.classname = classname;
+ }
+
+ /**
+ * Returns the descriptive error message for this exception. It will
+ * include the class name that caused the problem if known. This method
+ * overrides Throwable.getMessage()
+ *
+ * @return A descriptive error message
+ */
+ public String getMessage()
+ {
+ return super.getMessage() + (classname == null ? "" : ": " + classname);
+ }
}
-
-/*************************************************************************/
-
-/**
- * Create a new InvalidClassException with a descriptive error message
- * String, and the name of the class that caused the problem.
- *
- * @param classname The number of bytes tranferred before the interruption
- * @param message The descriptive error message
- */
-public
-InvalidClassException(String classname, String message)
-{
- super(message);
- this.classname = classname;
-}
-
-/*************************************************************************/
-
-/*
- * Instance Methods
- */
-
-/**
- * Returns the descriptive error message for this exception. It will
- * include the class name that caused the problem if known. This method
- * overrides Throwable.getMessage()
- *
- * @return A descriptive error message
- */
-public String
-getMessage()
-{
- return(super.getMessage() + ": " + classname);
-}
-
-} // class InvalidClassException
Index: java/util/ResourceBundle.java
===================================================================
RCS file: /cvs/gcc/egcs/libjava/java/util/ResourceBundle.java,v
retrieving revision 1.11
diff -u -r1.11 ResourceBundle.java
--- ResourceBundle.java 2000/12/15 15:49:50 1.11
+++ ResourceBundle.java 2001/05/06 14:01:48
@@ -83,9 +83,7 @@
{
try
{
- // This call is wrong by the spec, but it will have to
- // do until our Class.forName is fixed.
- rbc = Class.forName(bundleName, loader);
+ rbc = Class.forName(bundleName, true, loader);
r = null;
try
{
Index: gnu/gcj/runtime/VMClassLoader.java
===================================================================
RCS file: /cvs/gcc/egcs/libjava/gnu/gcj/runtime/VMClassLoader.java,v
retrieving revision 1.5
diff -u -r1.5 VMClassLoader.java
--- VMClassLoader.java 2000/08/26 19:25:13 1.5
+++ VMClassLoader.java 2001/05/06 14:01:48
@@ -65,18 +65,11 @@
/** This is overridden to search the internal hash table, which
* will only search existing linked-in classes. This will make
* the default implementation of loadClass (in ClassLoader) work right.
+ * The implementation of this method is in java/lang/natClassLoader.cc.
*/
- protected final native Class findSystemClass(String name)
- throws java.lang.ClassNotFoundException, java.lang.LinkageError;
+ protected native Class findClass(String name)
+ throws java.lang.ClassNotFoundException;
- // Return the sole VMClassLoader.
- private static synchronized VMClassLoader getVMClassLoader ()
- {
- if (redirect == null)
- redirect = new VMClassLoader ();
- return redirect;
- }
-
// The only VMClassLoader that can exist.
- private static VMClassLoader redirect;
+ public static VMClassLoader instance = new VMClassLoader ();
}