diff options
author | Bryce McKinlay <bryce@gcc.gnu.org> | 2005-02-22 03:13:35 +0000 |
---|---|---|
committer | Bryce McKinlay <bryce@gcc.gnu.org> | 2005-02-22 03:13:35 +0000 |
commit | f4294557b7ebb12ab58c9b57e1309d5f2fcfb019 (patch) | |
tree | 3b41b785f371a92850d3442fff7b7deb7e7ec0c4 /libjava/java/io/ObjectInputStream.java | |
parent | bb2e1640492f6b6989131cef45519dfd47a1acbb (diff) | |
download | gcc-f4294557b7ebb12ab58c9b57e1309d5f2fcfb019.zip gcc-f4294557b7ebb12ab58c9b57e1309d5f2fcfb019.tar.gz gcc-f4294557b7ebb12ab58c9b57e1309d5f2fcfb019.tar.bz2 |
[multiple changes]
2005-02-21 Bryce McKinlay <mckinlay@redhat.com>
Merge serialization from GNU Classpath.
* gcj/method.h: Add missing #includes.
* java/io/ObjectInputStream.java (readClassDescriptor): Check for
primitive class IDs on the stream here...
(resolveClass): ...not here.
* java/io/ObjectStreamField.java: Use VMObjectStream class calls to set
fields.
* java/io/VMObjectStreamClass.java (setDoubleNative, setFloatNative,
setLongNative, setIntNative, setShortNative, setCharNative,
setByteNative, setBooleanNative, setObjectNative): New native methods.
* java/io/natVMObjectStreamClass.java (setDoubleNative, setFloatNative,
setLongNative, setIntNative, setShortNative, setCharNative,
setByteNative, setBooleanNative, setObjectNative): Implement them.
* java/io/natObjectInputStream.cc (allocateObject): Add new parameters
from Classpath's version. Use _Jv_FromReflectedConstructor(). Call
the constructor here.
(callConstructor): Removed.
(getCallersClassLoader): Removed.
* java/lang/reflect/Field.java (setByte, setShort, setInt, setLong,
setFloat, setDouble, setChar, setBoolean): Add 'checkFinal' parameter
to control whether setting final field values is permitted. Call
getAddr() with checkFinal parameter instead of setAddr().
* java/lang/reflect/natField.cc (getType): Lookup and resolve field
only if not done already.
(getAddr): Add checkFinal parameter. Do the final field check only if
checkFinal is set.
(setAddr): Removed.
2005-02-21 Mark Wielaard <mark@klomp.org>
# Fixes bug #11957
* java/io/ObjectInputStream.java (resolveClass): Don't check "void"
twice.
2005-02-21 Mark Wielaard <mark@klomp.org>
Fixes bug #11618.
* java/io/ObjectInputStream.java (readClassDescriptor): Handle classes
without a super class and us ObjectStreamClass.lookupForClassObject().
(resolveClass): Check for primitive types.
(lookupClass): Return null when argument is null.
2005-02-21 Jeroen Frijters <jeroen@frijters.net>
* java/io/ObjectInputStream.java
(readObject): Fix to consume TC_ENDBLOCKDATA after readExternal.
2005-02-21 Jeroen Frijters <jeroen@frijters.net>
* java/io/ObjectOutputStream.java
(writeObject, callWriteMethod): Replaced reflection with accessing
cached info in ObjectStreamClass.
(getMethod): Removed.
* java/io/ObjectStreamClass.java
(findMethod): Added check to make sure the method found has the
right modifiers.
(cacheMethods): Added writeReplace and writeObject methods.
(setFlags): Look at new writeObjectMethod field instead of doing
reflection again.
(writeReplaceMethod): New field.
(writeObjectMethod): New field.
2005-02-21 Guilhem Lavaux <guilhem@kaffe.org>
Jeroen Frijters <jeroen@frijters.net>
* java/io/ObjectInputStream.java
(newObject): Changed prototype. Get a constructor reflect object
directly.
(callConstructor): Removed.
(allocateObject): Changed prototype.
(readClassDescriptor): Build the constructor reflection directly.
(readObject): Invoke newObject using the new prototype.
* java/io/ObjectStreamClass.java
(firstNonSerializableParent): Removed.
(firstNonSerializableParentConstructor): Added.
From-SVN: r95378
Diffstat (limited to 'libjava/java/io/ObjectInputStream.java')
-rw-r--r-- | libjava/java/io/ObjectInputStream.java | 127 |
1 files changed, 93 insertions, 34 deletions
diff --git a/libjava/java/io/ObjectInputStream.java b/libjava/java/io/ObjectInputStream.java index 6f4faf8..2cfe4c9 100644 --- a/libjava/java/io/ObjectInputStream.java +++ b/libjava/java/io/ObjectInputStream.java @@ -43,6 +43,7 @@ import gnu.classpath.Configuration; import gnu.java.io.ObjectIdentityWrapper; import java.lang.reflect.Array; +import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -122,15 +123,6 @@ public class ObjectInputStream extends InputStream */ public final Object readObject() throws ClassNotFoundException, IOException { - if (callersClassLoader == null) - { - callersClassLoader = getCallersClassLoader (); - if (Configuration.DEBUG && dump) - { - dumpElementln ("CallersClassLoader = " + callersClassLoader); - } - } - if (this.useSubclassMethod) return readObjectOverride(); @@ -272,7 +264,7 @@ public class ObjectInputStream extends InputStream readArrayElements(array, componentType); if(dump) for (int i = 0, len = Array.getLength(array); i < len; i++) - dumpElementln(" ELEMENT[" + i + "]=" + Array.get(array, i)); + dumpElementln(" ELEMENT[" + i + "]=" + Array.get(array, i)); ret_val = processResolution(null, array, handle); break; } @@ -302,13 +294,18 @@ public class ObjectInputStream extends InputStream obj.readExternal(this); if (read_from_blocks) - setBlockDataMode(oldmode); + { + setBlockDataMode(oldmode); + if (!oldmode) + if (this.realInputStream.readByte() != TC_ENDBLOCKDATA) + throw new IOException("No end of block data seen for class with readExternal (ObjectInputStream) method."); + } ret_val = processResolution(osc, obj, handle); break; } // end if (osc.realClassIsExternalizable) - Object obj = newObject(clazz, osc.firstNonSerializableParent); + Object obj = newObject(clazz, osc.firstNonSerializableParentConstructor); int handle = assignNewHandle(obj); Object prevObject = this.currentObject; @@ -399,8 +396,6 @@ public class ObjectInputStream extends InputStream setBlockDataMode(old_mode); this.isDeserializing = was_deserializing; - - depth -= 2; depth -= 2; @@ -506,7 +501,8 @@ public class ObjectInputStream extends InputStream flags, fields); assignNewHandle(osc); - ClassLoader currentLoader = currentLoader(); + if (callersClassLoader == null) + callersClassLoader = currentLoader(); for (int i = 0; i < field_count; i++) { @@ -527,12 +523,40 @@ public class ObjectInputStream extends InputStream class_name = String.valueOf(type_code); fields[i] = - new ObjectStreamField(field_name, class_name, currentLoader); + new ObjectStreamField(field_name, class_name, callersClassLoader); } /* Now that fields have been read we may resolve the class * (and read annotation if needed). */ - Class clazz = resolveClass(osc); + Class clazz; + try + { + clazz = resolveClass(osc); + } + catch (ClassNotFoundException cnfe) + { + // Maybe it was an primitive class? + if (name.equals("void")) + clazz = Void.TYPE; + else if (name.equals("boolean")) + clazz = Boolean.TYPE; + else if (name.equals("byte")) + clazz = Byte.TYPE; + else if (name.equals("short")) + clazz = Short.TYPE; + else if (name.equals("char")) + clazz = Character.TYPE; + else if (name.equals("int")) + clazz = Integer.TYPE; + else if (name.equals("long")) + clazz = Long.TYPE; + else if (name.equals("float")) + clazz = Float.TYPE; + else if (name.equals("double")) + clazz = Double.TYPE; + else + throw cnfe; + } boolean oldmode = setBlockDataMode(true); osc.setClass(clazz, lookupClass(clazz.getSuperclass())); @@ -542,16 +566,45 @@ public class ObjectInputStream extends InputStream // find the first non-serializable, non-abstract // class in clazz's inheritance hierarchy Class first_nonserial = clazz.getSuperclass(); - while (Serializable.class.isAssignableFrom(first_nonserial) - || Modifier.isAbstract(first_nonserial.getModifiers())) + // Maybe it is a primitive class, those don't have a super class, + // or Object itself. Otherwise we can keep getting the superclass + // till we hit the Object class, or some other non-serializable class. + + if (first_nonserial == null) + first_nonserial = clazz; + else + while (Serializable.class.isAssignableFrom(first_nonserial) + || Modifier.isAbstract(first_nonserial.getModifiers())) first_nonserial = first_nonserial.getSuperclass(); - osc.firstNonSerializableParent = first_nonserial; + final Class local_constructor_class = first_nonserial; + + osc.firstNonSerializableParentConstructor = + (Constructor)AccessController.doPrivileged(new PrivilegedAction() + { + public Object run() + { + try + { + Constructor c = local_constructor_class. + getDeclaredConstructor(new Class[0]); + if (Modifier.isPrivate(c.getModifiers())) + return null; + return c; + } + catch (NoSuchMethodException e) + { + // error will be reported later, in newObject() + return null; + } + } + }); + osc.realClassIsSerializable = Serializable.class.isAssignableFrom(clazz); osc.realClassIsExternalizable = Externalizable.class.isAssignableFrom(clazz); ObjectStreamField[] stream_fields = osc.fields; - ObjectStreamField[] real_fields = ObjectStreamClass.lookup(clazz).fields; + ObjectStreamField[] real_fields = ObjectStreamClass.lookupForClassObject(clazz).fields; ObjectStreamField[] fieldmapping = new ObjectStreamField[2 * Math.max(stream_fields.length, real_fields.length)]; int stream_idx = 0; @@ -717,6 +770,15 @@ public class ObjectInputStream extends InputStream protected Class resolveClass(ObjectStreamClass osc) throws ClassNotFoundException, IOException { + if (callersClassLoader == null) + { + callersClassLoader = currentLoader (); + if (Configuration.DEBUG && dump) + { + dumpElementln ("CallersClassLoader = " + callersClassLoader); + } + } + return Class.forName(osc.getName(), true, callersClassLoader); } @@ -750,8 +812,10 @@ public class ObjectInputStream extends InputStream */ private ObjectStreamClass lookupClass(Class clazz) { - ObjectStreamClass oclazz; + if (clazz == null) + return null; + ObjectStreamClass oclazz; oclazz = (ObjectStreamClass)classLookupTable.get(clazz); if (oclazz == null) return ObjectStreamClass.lookup(clazz); @@ -1767,14 +1831,14 @@ public class ObjectInputStream extends InputStream // returns a new instance of REAL_CLASS that has been constructed // only to the level of CONSTRUCTOR_CLASS (a super class of REAL_CLASS) - private Object newObject (Class real_class, Class constructor_class) - throws ClassNotFoundException + private Object newObject (Class real_class, Constructor constructor) + throws ClassNotFoundException, IOException { + if (constructor == null) + throw new InvalidClassException("Missing accessible no-arg base class constructor for " + real_class.getName()); try { - Object obj = allocateObject (real_class); - callConstructor (constructor_class, obj); - return obj; + return allocateObject(real_class, constructor.getDeclaringClass(), constructor); } catch (InstantiationException e) { @@ -1810,8 +1874,6 @@ public class ObjectInputStream extends InputStream * @return The current class loader in the calling stack. */ private static native ClassLoader currentClassLoader (SecurityManager sm); - - private native ClassLoader getCallersClassLoader(); private void callReadMethod (Method readObject, Class klass, Object obj) throws ClassNotFoundException, IOException @@ -1844,11 +1906,9 @@ public class ObjectInputStream extends InputStream prereadFields = null; } - private native Object allocateObject (Class clazz) + private native Object allocateObject(Class clazz, Class constr_clazz, Constructor constructor) throws InstantiationException; - private native void callConstructor (Class clazz, Object obj); - private static final int BUFFER_SIZE = 1024; private DataInputStream realInputStream; @@ -1870,9 +1930,8 @@ public class ObjectInputStream extends InputStream private Hashtable classLookupTable; private GetField prereadFields; - private static boolean dump = false && Configuration.DEBUG; - private ClassLoader callersClassLoader; + private static boolean dump; // The nesting depth for debugging output private int depth = 0; |