diff options
author | Jeroen Frijters <jeroen@frijters.net> | 2004-02-06 13:27:36 +0000 |
---|---|---|
committer | Michael Koch <mkoch@gcc.gnu.org> | 2004-02-06 13:27:36 +0000 |
commit | 2941cc061a7a0cafdfa0aec2be9387c92b590625 (patch) | |
tree | fb6663e4a39d87f86d5337e6215ad1769df33c95 /libjava/java | |
parent | eb457a7a0791d32d9b0df5ff8425abe59a9bee75 (diff) | |
download | gcc-2941cc061a7a0cafdfa0aec2be9387c92b590625.zip gcc-2941cc061a7a0cafdfa0aec2be9387c92b590625.tar.gz gcc-2941cc061a7a0cafdfa0aec2be9387c92b590625.tar.bz2 |
ObjectInputStream.java: Made all calls to dumpElement[ln] conditional on dump flag.
2004-02-06 Jeroen Frijters <jeroen@frijters.net>
* java/io/ObjectInputStream.java: Made all calls
to dumpElement[ln] conditional on dump flag. (readObject): Changed to
use cached info from ObjectStreamClass. (readClassDescriptor):
Cache more information in ObjectStreamClass. (processResolution,
readFields): Use cached info from ObjectStreamClass.
(newObject): Throw exception instead of returning null for failure.
(getField, getMethod, callReadMethod, setBooleanField, setByteField,
setCharField, setDoubleField, setFloatField, setIntField,
setLongField, setShortField, setObjectField, readObjectParams):
Removed. (dumpElement, dumpElementln): Removed dump flag condition
check.
* java/io/ObjectStreamField.java (hasReadMethod): Removed.
(setClass): Added call to cacheMethods() (findMethod): New method.
(cacheMethods): New method. (ObjectStreamClass): Added call to
cacheMethods(). (setFields): Cache fields. (getClassUID): Use
AccessController.doPrivileged to invoke setAccessible.
(readObjectMethod, readResolveMethod, realClassIsSerializable,
realClassIsExternalizable, fieldMapping, firstNonSerializableParent):
New fields.
* java/io/ObjectStreamField.java (ObjectStreamField): New constructor.
(ObjectStreamField): Removed FIXME workaround. (getTypeString,
isPrimitive): Made safe for cases where type == null.
(setBooleanField, setByteField, setCharField, setShortField,
setIntField, setLongField, setFloatField, setDoubleField,
setObjectField): New methods.
From-SVN: r77395
Diffstat (limited to 'libjava/java')
-rw-r--r-- | libjava/java/io/ObjectInputStream.java | 807 | ||||
-rw-r--r-- | libjava/java/io/ObjectStreamClass.java | 121 | ||||
-rw-r--r-- | libjava/java/io/ObjectStreamField.java | 125 |
3 files changed, 458 insertions, 595 deletions
diff --git a/libjava/java/io/ObjectInputStream.java b/libjava/java/io/ObjectInputStream.java index a277691..d0def09 100644 --- a/libjava/java/io/ObjectInputStream.java +++ b/libjava/java/io/ObjectInputStream.java @@ -138,7 +138,7 @@ public class ObjectInputStream extends InputStream this.isDeserializing = true; byte marker = this.realInputStream.readByte(); - dumpElement("MARKER: 0x" + Integer.toHexString(marker) + " "); + if(dump) dumpElement("MARKER: 0x" + Integer.toHexString(marker) + " "); try { @@ -155,25 +155,25 @@ public class ObjectInputStream extends InputStream case TC_BLOCKDATALONG: { if (marker == TC_BLOCKDATALONG) - dumpElementln("BLOCKDATALONG"); + if(dump) dumpElementln("BLOCKDATALONG"); else - dumpElementln("BLOCKDATA"); + if(dump) dumpElementln("BLOCKDATA"); readNextBlock(marker); throw new StreamCorruptedException("Unexpected blockData"); } case TC_NULL: { - dumpElementln("NULL"); + if(dump) dumpElementln("NULL"); ret_val = null; break; } case TC_REFERENCE: { - dumpElement("REFERENCE "); + if(dump) dumpElement("REFERENCE "); Integer oid = new Integer(this.realInputStream.readInt()); - dumpElementln(Integer.toHexString(oid.intValue())); + if(dump) dumpElementln(Integer.toHexString(oid.intValue())); ret_val = ((ObjectIdentityWrapper) this.objectLookupTable.get(oid)).object; break; @@ -181,7 +181,7 @@ public class ObjectInputStream extends InputStream case TC_CLASS: { - dumpElementln("CLASS"); + if(dump) dumpElementln("CLASS"); ObjectStreamClass osc = (ObjectStreamClass)readObject(); Class clazz = osc.forClass(); assignNewHandle(clazz); @@ -191,7 +191,7 @@ public class ObjectInputStream extends InputStream case TC_PROXYCLASSDESC: { - dumpElementln("PROXYCLASS"); + if(dump) dumpElementln("PROXYCLASS"); int n_intf = this.realInputStream.readInt(); String[] intfs = new String[n_intf]; for (int i = 0; i < n_intf; i++) @@ -242,41 +242,42 @@ public class ObjectInputStream extends InputStream case TC_STRING: case TC_LONGSTRING: { - dumpElement("STRING="); + if(dump) dumpElement("STRING="); String s = this.realInputStream.readUTF(); - dumpElementln(s); - ret_val = processResolution(s, assignNewHandle(s)); + if(dump) dumpElementln(s); + ret_val = processResolution(null, s, assignNewHandle(s)); break; } case TC_ARRAY: { - dumpElementln("ARRAY"); + if(dump) dumpElementln("ARRAY"); ObjectStreamClass osc = (ObjectStreamClass)readObject(); Class componentType = osc.forClass().getComponentType(); - dumpElement("ARRAY LENGTH="); + if(dump) dumpElement("ARRAY LENGTH="); int length = this.realInputStream.readInt(); - dumpElementln (length + "; COMPONENT TYPE=" + componentType); + if(dump) dumpElementln (length + "; COMPONENT TYPE=" + componentType); Object array = Array.newInstance(componentType, length); int handle = assignNewHandle(array); readArrayElements(array, componentType); - for (int i = 0, len = Array.getLength(array); i < len; i++) - dumpElementln(" ELEMENT[" + i + "]=" + Array.get(array, i)); - ret_val = processResolution(array, handle); + if(dump) + for (int i = 0, len = Array.getLength(array); i < len; i++) + dumpElementln(" ELEMENT[" + i + "]=" + Array.get(array, i)); + ret_val = processResolution(null, array, handle); break; } case TC_OBJECT: { - dumpElementln("OBJECT"); + if(dump) dumpElementln("OBJECT"); ObjectStreamClass osc = (ObjectStreamClass)readObject(); Class clazz = osc.forClass(); - if (!Serializable.class.isAssignableFrom(clazz)) + if (!osc.realClassIsSerializable) throw new NotSerializableException (clazz + " is not Serializable, and thus cannot be deserialized."); - if (Externalizable.class.isAssignableFrom(clazz)) + if (osc.realClassIsExternalizable) { Externalizable obj = null; @@ -315,23 +316,11 @@ public class ObjectInputStream extends InputStream if (read_from_blocks) setBlockDataMode(oldmode); - ret_val = processResolution(obj, handle); + ret_val = processResolution(osc, obj, handle); break; - } // end if (Externalizable.class.isAssignableFrom (clazz)) - - // 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())) - first_nonserial = first_nonserial.getSuperclass(); - - Object obj = null; - obj = newObject(clazz, first_nonserial); - - if (obj == null) - throw new ClassNotFoundException - ("Instance of " + clazz + " could not be created"); + } // end if (osc.realClassIsExternalizable) + + Object obj = newObject(clazz, osc.firstNonSerializableParent); int handle = assignNewHandle(obj); this.currentObject = obj; @@ -342,20 +331,21 @@ public class ObjectInputStream extends InputStream { this.currentObjectStreamClass = hierarchy[i]; - dumpElementln("Reading fields of " + this.currentObjectStreamClass.getName ()); + if(dump) dumpElementln("Reading fields of " + this.currentObjectStreamClass.getName ()); // XXX: should initialize fields in classes in the hierarchy // that aren't in the stream // should skip over classes in the stream that aren't in the // real classes hierarchy - if (this.currentObjectStreamClass.hasReadMethod()) + Method readObjectMethod = this.currentObjectStreamClass.readObjectMethod; + if (readObjectMethod != null) { fieldsAlreadyRead = false; boolean oldmode = setBlockDataMode(true); - callReadMethod(obj, this.currentObjectStreamClass); + callReadMethod(readObjectMethod, this.currentObjectStreamClass.forClass(), obj); setBlockDataMode(oldmode); - dumpElement("ENDBLOCKDATA? "); + if(dump) dumpElement("ENDBLOCKDATA? "); try { // FIXME: XXX: This try block is to catch EOF which is @@ -363,15 +353,15 @@ public class ObjectInputStream extends InputStream if (this.realInputStream.readByte() != TC_ENDBLOCKDATA) throw new IOException ("No end of block data seen for class with readObject (ObjectInputStream) method."); - dumpElementln("yes"); + if(dump) dumpElementln("yes"); } catch (EOFException e) { - dumpElementln("no, got EOFException"); + if(dump) dumpElementln("no, got EOFException"); } catch (IOException e) { - dumpElementln("no, got IOException"); + if(dump) dumpElementln("no, got IOException"); } } else @@ -382,21 +372,21 @@ public class ObjectInputStream extends InputStream this.currentObject = null; this.currentObjectStreamClass = null; - ret_val = processResolution(obj, handle); + ret_val = processResolution(osc, obj, handle); break; } case TC_RESET: - dumpElementln("RESET"); + if(dump) dumpElementln("RESET"); clearHandles(); ret_val = readObject(); break; case TC_EXCEPTION: { - dumpElement("EXCEPTION="); + if(dump) dumpElement("EXCEPTION="); Exception e = (Exception)readObject(); - dumpElementln(e.toString()); + if(dump) dumpElementln(e.toString()); clearHandles(); throw new WriteAbortedException("Exception thrown during writing of stream", e); } @@ -440,27 +430,29 @@ public class ObjectInputStream extends InputStream protected ObjectStreamClass readClassDescriptor() throws ClassNotFoundException, IOException { - dumpElement("CLASSDESC NAME="); + if(dump) dumpElement("CLASSDESC NAME="); String name = this.realInputStream.readUTF(); - dumpElement(name + "; UID="); + if(dump) dumpElement(name + "; UID="); long uid = this.realInputStream.readLong (); - dumpElement(Long.toHexString(uid) + "; FLAGS="); + if(dump) dumpElement(Long.toHexString(uid) + "; FLAGS="); byte flags = this.realInputStream.readByte (); - dumpElement(Integer.toHexString(flags) + "; FIELD COUNT="); + if(dump) dumpElement(Integer.toHexString(flags) + "; FIELD COUNT="); short field_count = this.realInputStream.readShort(); - dumpElementln(Short.toString(field_count)); + if(dump) dumpElementln(Short.toString(field_count)); ObjectStreamField[] fields = new ObjectStreamField[field_count]; ObjectStreamClass osc = new ObjectStreamClass(name, uid, flags, fields); assignNewHandle(osc); + + ClassLoader currentLoader = currentLoader(); for (int i = 0; i < field_count; i++) { - dumpElement(" TYPE CODE="); + if(dump) dumpElement(" TYPE CODE="); char type_code = (char)this.realInputStream.readByte(); - dumpElement(type_code + "; FIELD NAME="); + if(dump) dumpElement(type_code + "; FIELD NAME="); String field_name = this.realInputStream.readUTF(); - dumpElementln(field_name); + if(dump) dumpElementln(field_name); String class_name; // If the type code is an array or an object we must @@ -473,35 +465,87 @@ 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, currentLoader); } /* Now that fields have been read we may resolve the class * (and read annotation if needed). */ Class clazz = resolveClass(osc); - - for (int i = 0; i < field_count; i++) + + boolean oldmode = setBlockDataMode(true); + osc.setClass(clazz, lookupClass(clazz.getSuperclass())); + classLookupTable.put(clazz, osc); + setBlockDataMode(oldmode); + + // 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())) + first_nonserial = first_nonserial.getSuperclass(); + + osc.firstNonSerializableParent = first_nonserial; + 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[] fieldmapping = new ObjectStreamField[2 * Math.max(stream_fields.length, real_fields.length)]; + osc.fieldMapping = fieldmapping; + + int stream_idx = 0; + int real_idx = 0; + int map_idx = 0; + + while (stream_idx < stream_fields.length + || real_idx < real_fields.length) { - Field f; - - try + ObjectStreamField stream_field = null; + ObjectStreamField real_field = null; + + if (stream_idx == stream_fields.length) { - f = clazz.getDeclaredField(fields[i].getName()); - if (f != null && !f.getType().equals(fields[i].getType())) - throw new InvalidClassException - ("invalid field type for " + fields[i].getName() + " in class " - + name + " (requested was \"" + fields[i].getType() - + " and found \"" + f.getType() + "\")"); + real_field = real_fields[real_idx++]; } - catch (NoSuchFieldException _) + else if (real_idx == real_fields.length) { + stream_field = stream_fields[stream_idx++]; } - } + else + { + int comp_val = + real_fields[real_idx].compareTo (stream_fields[stream_idx]); - boolean oldmode = setBlockDataMode(true); - osc.setClass(clazz, lookupClass(clazz.getSuperclass())); - classLookupTable.put(clazz, osc); - setBlockDataMode(oldmode); + if (comp_val < 0) + { + real_field = real_fields[real_idx++]; + } + else if (comp_val > 0) + { + stream_field = stream_fields[stream_idx++]; + } + else + { + stream_field = stream_fields[stream_idx++]; + real_field = real_fields[real_idx++]; + if(stream_field.getType() != real_field.getType()) + throw new InvalidClassException + ("invalid field type for " + real_field.getName() + + " in class " + name); + } + } + if (stream_field != null) + { + if (stream_field.getOffset() < 0) + stream_field = null; + else if (!stream_field.isToSet()) + real_field = null; + } + if (real_field != null && !real_field.isToSet()) + real_field = null; + fieldmapping[map_idx++] = stream_field; + fieldmapping[map_idx++] = real_field; + } return osc; } @@ -763,11 +807,11 @@ public class ObjectInputStream extends InputStream protected void readStreamHeader() throws IOException, StreamCorruptedException { - dumpElement("STREAM MAGIC "); + if(dump) dumpElement("STREAM MAGIC "); if (this.realInputStream.readShort() != STREAM_MAGIC) throw new StreamCorruptedException("Invalid stream magic number"); - dumpElementln("STREAM VERSION "); + if(dump) dumpElementln("STREAM VERSION "); if (this.realInputStream.readShort() != STREAM_VERSION) throw new StreamCorruptedException("Invalid stream version number"); } @@ -1045,7 +1089,7 @@ public class ObjectInputStream extends InputStream * deserializing class (if present). It cannot (and should not)be called * outside of it. Its goal is to read all fields in the real input stream * and keep them accessible through the {@link #GetField} class. Calling - * this method will not alterate the deserializing object. + * this method will not alter the deserializing object. * * @return A valid freshly created 'GetField' instance to get access to * the deserialized stream. @@ -1375,20 +1419,18 @@ public class ObjectInputStream extends InputStream return this.nextOID++; } - private Object processResolution(Object obj, int handle) + private Object processResolution(ObjectStreamClass osc, Object obj, int handle) throws IOException { - if (obj instanceof Serializable) + if (osc != null && obj instanceof Serializable) { - Method m = null; try { - Class classArgs[] = {}; - m = getMethod(obj.getClass(), "readResolve", classArgs); - obj = m.invoke(obj, new Object[] {}); - } - catch (NoSuchMethodException ignore) - { + Method m = osc.readResolveMethod; + if(m != null) + { + obj = m.invoke(obj, new Object[] {}); + } } catch (IllegalAccessException ignore) { @@ -1422,15 +1464,15 @@ public class ObjectInputStream extends InputStream { if (marker == TC_BLOCKDATA) { - dumpElement("BLOCK DATA SIZE="); + if(dump) dumpElement("BLOCK DATA SIZE="); this.blockDataBytes = this.realInputStream.readUnsignedByte(); - dumpElementln (Integer.toString(this.blockDataBytes)); + if(dump) dumpElementln (Integer.toString(this.blockDataBytes)); } else if (marker == TC_BLOCKDATALONG) { - dumpElement("BLOCK DATA LONG SIZE="); + if(dump) dumpElement("BLOCK DATA LONG SIZE="); this.blockDataBytes = this.realInputStream.readInt(); - dumpElementln (Integer.toString(this.blockDataBytes)); + if(dump) dumpElementln (Integer.toString(this.blockDataBytes)); } else { @@ -1517,159 +1559,124 @@ public class ObjectInputStream extends InputStream private void readFields (Object obj, ObjectStreamClass stream_osc) throws ClassNotFoundException, IOException { - ObjectStreamField[] stream_fields = stream_osc.fields; - ObjectStreamField[] real_fields = - lookupClass(stream_osc.forClass()).fields; - - boolean default_initialize, set_value; - String field_name = null; - Class type = null; - ObjectStreamField stream_field = null; - ObjectStreamField real_field = null; - int stream_idx = 0; - int real_idx = 0; + ObjectStreamField[] fields = stream_osc.fieldMapping; - while (stream_idx < stream_fields.length - && real_idx < real_fields.length) + for (int i = 0; i < fields.length; i += 2) { - default_initialize = false; - set_value = true; - - if (stream_idx == stream_fields.length) - default_initialize = true; - else - { - stream_field = stream_fields[stream_idx]; - type = stream_field.getType(); - } - - if (real_idx == real_fields.length) - set_value = false; - else + ObjectStreamField stream_field = fields[i]; + ObjectStreamField real_field = fields[i + 1]; + if(stream_field != null || real_field != null) { - real_field = real_fields[real_idx]; - type = real_field.getType(); - field_name = real_field.getName(); - } - - if (set_value && !default_initialize) - { - int comp_val = - real_field.compareTo (stream_field); - - if (comp_val < 0) + boolean read_value = stream_field != null; + boolean set_value = real_field != null; + String field_name; + char type; + if (stream_field != null) { - default_initialize = true; - real_idx++; - } - else if (comp_val > 0) - { - set_value = false; - stream_idx++; + field_name = stream_field.getName(); + type = stream_field.getTypeCode(); } else { - real_idx++; - stream_idx++; + field_name = real_field.getName(); + type = real_field.getTypeCode(); } - } - - if (stream_field.getOffset() < 0) - { - default_initialize = true; - set_value = false; - } - - if (!stream_field.isToSet()) - set_value = false; - try - { - if (type == Boolean.TYPE) - { - boolean value = - default_initialize ? false : this.realInputStream.readBoolean(); - if (!default_initialize && set_value) - dumpElementln(" " + field_name + ": " + value); - if (set_value) - setBooleanField(obj, stream_osc.forClass(), field_name, value); - } - else if (type == Byte.TYPE) - { - byte value = - default_initialize ? 0 : this.realInputStream.readByte(); - if (!default_initialize && set_value) - dumpElementln(" " + field_name + ": " + value); - if (set_value) - setByteField(obj, stream_osc.forClass(), field_name, value); - } - else if (type == Character.TYPE) - { - char value = - default_initialize ? (char)0 : this.realInputStream.readChar(); - if (!default_initialize && set_value) - dumpElementln(" " + field_name + ": " + value); - if (set_value) - setCharField(obj, stream_osc.forClass(), field_name, value); - } - else if (type == Double.TYPE) - { - double value = - default_initialize ? 0 : this.realInputStream.readDouble(); - if (!default_initialize && set_value) - dumpElementln(" " + field_name + ": " + value); - if (set_value) - setDoubleField(obj, stream_osc.forClass(), field_name, value); - } - else if (type == Float.TYPE) - { - float value = - default_initialize ? 0 : this.realInputStream.readFloat(); - if (!default_initialize && set_value) - dumpElementln(" " + field_name + ": " + value); - if (set_value) - setFloatField(obj, stream_osc.forClass(), field_name, value); - } - else if (type == Integer.TYPE) - { - int value = - default_initialize ? 0 : this.realInputStream.readInt(); - if (!default_initialize && set_value) - dumpElementln(" " + field_name + ": " + value); - if (set_value) - setIntField(obj, stream_osc.forClass(), field_name, value); - } - else if (type == Long.TYPE) - { - long value = - default_initialize ? 0 : this.realInputStream.readLong(); - if (!default_initialize && set_value) - dumpElementln(" " + field_name + ": " + value); - if (set_value) - setLongField(obj, stream_osc.forClass(), field_name, value); - } - else if (type == Short.TYPE) - { - short value = - default_initialize ? (short)0 : this.realInputStream.readShort(); - if (!default_initialize && set_value) - dumpElementln(" " + field_name + ": " + value); - if (set_value) - setShortField(obj, stream_osc.forClass(), field_name, value); - } - else + switch(type) { - Object value = - default_initialize ? null : readObject(); - if (set_value) - setObjectField(obj, stream_osc.forClass(), field_name, - real_field.getTypeString(), value); + case 'Z': + { + boolean value = + read_value ? this.realInputStream.readBoolean() : false; + if (dump && read_value && set_value) + dumpElementln(" " + field_name + ": " + value); + if (set_value) + real_field.setBooleanField(obj, value); + break; + } + case 'B': + { + byte value = + read_value ? this.realInputStream.readByte() : 0; + if (dump && read_value && set_value) + dumpElementln(" " + field_name + ": " + value); + if (set_value) + real_field.setByteField(obj, value); + break; + } + case 'C': + { + char value = + read_value ? this.realInputStream.readChar(): 0; + if (dump && read_value && set_value) + dumpElementln(" " + field_name + ": " + value); + if (set_value) + real_field.setCharField(obj, value); + break; + } + case 'D': + { + double value = + read_value ? this.realInputStream.readDouble() : 0; + if (dump && read_value && set_value) + dumpElementln(" " + field_name + ": " + value); + if (set_value) + real_field.setDoubleField(obj, value); + break; + } + case 'F': + { + float value = + read_value ? this.realInputStream.readFloat() : 0; + if (dump && read_value && set_value) + dumpElementln(" " + field_name + ": " + value); + if (set_value) + real_field.setFloatField(obj, value); + break; + } + case 'I': + { + int value = + read_value ? this.realInputStream.readInt() : 0; + if (dump && read_value && set_value) + dumpElementln(" " + field_name + ": " + value); + if (set_value) + real_field.setIntField(obj, value); + break; + } + case 'J': + { + long value = + read_value ? this.realInputStream.readLong() : 0; + if (dump && read_value && set_value) + dumpElementln(" " + field_name + ": " + value); + if (set_value) + real_field.setLongField(obj, value); + break; + } + case 'S': + { + short value = + read_value ? this.realInputStream.readShort() : 0; + if (dump && read_value && set_value) + dumpElementln(" " + field_name + ": " + value); + if (set_value) + real_field.setShortField(obj, value); + break; + } + case 'L': + case '[': + { + Object value = + read_value ? readObject() : null; + if (set_value) + real_field.setObjectField(obj, value); + break; + } + default: + throw new InternalError("Invalid type code: " + type); } } - catch (NoSuchFieldError e) - { - dumpElementln("XXXX " + field_name + " does not exist."); - } } } @@ -1689,6 +1696,7 @@ 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 { try { @@ -1698,7 +1706,8 @@ public class ObjectInputStream extends InputStream } catch (InstantiationException e) { - return null; + throw new ClassNotFoundException + ("Instance of " + real_class + " could not be created"); } } @@ -1728,77 +1737,13 @@ public class ObjectInputStream extends InputStream * @param sm SecurityManager instance which should be called. * @return The current class loader in the calling stack. */ - private static ClassLoader currentClassLoader (SecurityManager sm) - { - // FIXME: This is too simple. - return ClassLoader.getSystemClassLoader (); - } - - /** - * This method tries to access a precise field called in the - * specified class. Before accessing the field, it tries to - * gain control on this field. If the field is either declared as - * not persistent or transient then it returns null - * immediately. - * - * @param klass Class to get the field from. - * @param name Name of the field to access. - * @return Field instance representing the requested field. - * @throws NoSuchFieldException if the field does not exist. - */ - private Field getField(Class klass, String name) - throws java.lang.NoSuchFieldException - { - final Field f = klass.getDeclaredField(name); - ObjectStreamField sf = lookupClass(klass).getField(name); - - AccessController.doPrivileged(new PrivilegedAction() - { - public Object run() - { - f.setAccessible(true); - return null; - } - }); - - /* We do not want to modify transient fields. They should - * be left to 0. - * N.B.: Not valid if the field is in serialPersistentFields. - */ - if (Modifier.isTransient(f.getModifiers()) && !sf.isPersistent()) - return null; - - return f; - } - - private static Method getMethod (Class klass, String name, Class args[]) - throws java.lang.NoSuchMethodException - { - final Method m = klass.getDeclaredMethod(name, args); - AccessController.doPrivileged(new PrivilegedAction() - { - public Object run() - { - m.setAccessible(true); - return null; - } - }); - return m; - } + private static native ClassLoader currentClassLoader (SecurityManager sm); - private void callReadMethod (Object obj, ObjectStreamClass osc) throws IOException + private void callReadMethod (Method readObject, Class klass, Object obj) throws IOException { - Class klass = osc.forClass(); try { - Class classArgs[] = {ObjectInputStream.class}; - Method m = getMethod (klass, "readObject", classArgs); - Object args[] = {this}; - m.invoke(obj, args); - } - catch (NoSuchMethodException nsme) - { - // Nothing. + readObject.invoke(obj, new Object[] { this }); } catch (InvocationTargetException x) { @@ -1827,265 +1772,7 @@ public class ObjectInputStream extends InputStream private native void callConstructor (Class clazz, Object obj); - /** - * This method writes a "boolean" value <code>val</code> in the specified field - * of the instance <code>obj</code> of the type <code>klass</code>. - * - * @param obj Instance to setup. - * @param klass Class type of the specified instance. - * @param field_name Name of the field in the specified class type. - * @param val The boolean value to write into the field. - * @throws InvalidClassException if the specified field has not the required type. - * @throws IOException if there is no field of that name in the specified class. - */ - private void setBooleanField(Object obj, Class klass, String field_name, - boolean val) throws IOException, InvalidClassException - { - try - { - Field f = getField(klass, field_name); - f.setBoolean(obj, val); - } - catch (IllegalArgumentException _) - { - throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name); - } - catch (Exception _) - { - } - } - - /** - * This method writes a "byte" value <code>val</code> in the specified field - * of the instance <code>obj</code> of the type <code>klass</code>. - * - * @param obj Instance to setup. - * @param klass Class type of the specified instance. - * @param field_name Name of the field in the specified class type. - * @param val The byte value to write into the field. - * @throws InvalidClassException if the specified field has not the required type. - * @throws IOException if there is no field of that name in the specified class. - */ - private void setByteField(Object obj, Class klass, String field_name, - byte val) throws IOException, InvalidClassException - { - try - { - Field f = getField(klass, field_name); - f.setByte(obj, val); - } - catch (IllegalArgumentException _) - { - throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name); - } - catch (Exception _) - { - } - } - - /** - * This method writes a "character" value <code>val</code> in the specified field - * of the instance <code>obj</code> of the type <code>klass</code>. - * - * @param obj Instance to setup. - * @param klass Class type of the specified instance. - * @param field_name Name of the field in the specified class type. - * @param val The character value to write into the field. - * @throws InvalidClassException if the specified field has not the required type. - * @throws IOException if there is no field of that name in the specified class. - */ - private void setCharField(Object obj, Class klass, String field_name, - char val) throws IOException, InvalidClassException - { - try - { - Field f = getField(klass, field_name); - f.setChar(obj, val); - } - catch (IllegalArgumentException _) - { - throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name); - } - catch (Exception _) - { - } - } - - /** - * This method writes a "double" value <code>val</code> in the specified field - * of the instance <code>obj</code> of the type <code>klass</code>. - * - * @param obj Instance to setup. - * @param klass Class type of the specified instance. - * @param field_name Name of the field in the specified class type. - * @param val The double value to write into the field. - * @throws InvalidClassException if the specified field has not the required type. - * @throws IOException if there is no field of that name in the specified class. - */ - private void setDoubleField(Object obj, Class klass, String field_name, - double val) throws IOException, InvalidClassException - { - try - { - Field f = getField(klass, field_name); - f.setDouble(obj, val); - } - catch (IllegalArgumentException _) - { - throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name); - } - catch (Exception _) - { - } - } - - /** - * This method writes a "float" value <code>val</code> in the specified field - * of the instance <code>obj</code> of the type <code>klass</code>. - * - * @param obj Instance to setup. - * @param klass Class type of the specified instance. - * @param field_name Name of the field in the specified class type. - * @param val The float value to write into the field. - * @throws InvalidClassException if the specified field has not the required type. - * @throws IOException if there is no field of that name in the specified class. - */ - private void setFloatField(Object obj, Class klass, String field_name, - float val) throws IOException, InvalidClassException - { - try - { - Field f = getField(klass, field_name); - f.setFloat(obj, val); - } - catch (IllegalArgumentException _) - { - throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name); - } - catch (Exception _) - { - } - } - - /** - * This method writes an "integer" value <code>val</code> in the specified field - * of the instance <code>obj</code> of the type <code>klass</code>. - * - * @param obj Instance to setup. - * @param klass Class type of the specified instance. - * @param field_name Name of the field in the specified class type. - * @param val The integer value to write into the field. - * @throws InvalidClassException if the specified field has not the required type. - * @throws IOException if there is no field of that name in the specified class. - */ - private void setIntField(Object obj, Class klass, String field_name, - int val) throws IOException, InvalidClassException - { - try - { - Field f = getField(klass, field_name); - f.setInt(obj, val); - } - catch (IllegalArgumentException _) - { - throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name); - } - catch (Exception _) - { - } - } - - /** - * This method writes the long value <code>val</code> in the specified field - * of the instance <code>obj</code> of the type <code>klass</code>. - * - * @param obj Instance to setup. - * @param klass Class type of the specified instance. - * @param field_name Name of the field in the specified class type. - * @param val The long value to write into the field. - * @throws InvalidClassException if the specified field has not the required type. - * @throws IOException if there is no field of that name in the specified class. - */ - private void setLongField(Object obj, Class klass, String field_name, - long val) throws IOException, InvalidClassException - { - try - { - Field f = getField(klass, field_name); - f.setLong(obj, val); - } - catch (IllegalArgumentException _) - { - throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name); - } - catch (Exception _) - { - } - } - - /** - * This method writes a "short" value <code>val</code> in the specified field - * of the instance <code>obj</code> of the type <code>klass</code>. - * - * @param obj Instance to setup. - * @param klass Class type of the specified instance. - * @param field_name Name of the field in the specified class type. - * @param val The short value to write into the field. - * @throws InvalidClassException if the specified field has not the required type. - * @throws IOException if there is no field of that name in the specified class. - */ - private void setShortField(Object obj, Class klass, String field_name, - short val) throws IOException, InvalidClassException - { - try - { - Field f = getField(klass, field_name); - f.setShort(obj, val); - } - catch (IllegalArgumentException _) - { - throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name); - } - catch (Exception _) - { - } - } - - /** - * This method writes an "object" value <code>val</code> in the specified field - * of the instance <code>obj</code> of the type <code>klass</code>. - * - * @param obj Instance to setup. - * @param klass Class type of the specified instance. - * @param field_name Name of the field in the specified class type. - * @param val The "object" value to write into the field. - * @throws InvalidClassException if the specified field has not the required type. - * @throws IOException if there is no field of that name in the specified class. - */ - private void setObjectField(Object obj, Class klass, String field_name, - String type_code, Object val) throws IOException, InvalidClassException - { - try - { - Field f = getField(klass, field_name); - ObjectStreamField of = new ObjectStreamField(field_name, f.getType()); - - if (of.getTypeString() == null || - !of.getTypeString().equals(type_code)) - throw new InvalidClassException("incompatible field type for " + klass.getName() + "." + field_name); - f.set(obj, val); - } - catch (InvalidClassException e) - { - throw e; - } - catch (Exception _) - { - } - } - private static final int BUFFER_SIZE = 1024; - private static final Class[] readObjectParams = { ObjectInputStream.class }; private DataInputStream realInputStream; private DataInputStream dataInputStream; @@ -2106,18 +1793,16 @@ public class ObjectInputStream extends InputStream private Hashtable classLookupTable; private GetField prereadFields; - private static boolean dump; + private static boolean dump = false && Configuration.DEBUG; private void dumpElement (String msg) { - if (Configuration.DEBUG && dump) - System.out.print(msg); + System.out.print(msg); } private void dumpElementln (String msg) { - if (Configuration.DEBUG && dump) - System.out.println(msg); + System.out.println(msg); } static diff --git a/libjava/java/io/ObjectStreamClass.java b/libjava/java/io/ObjectStreamClass.java index 5bd0e68..429db18 100644 --- a/libjava/java/io/ObjectStreamClass.java +++ b/libjava/java/io/ObjectStreamClass.java @@ -45,9 +45,11 @@ import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; +import java.security.AccessController; import java.security.DigestOutputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.security.PrivilegedAction; import java.security.Security; import java.util.Arrays; import java.util.Comparator; @@ -192,29 +194,6 @@ public class ObjectStreamClass implements Serializable return (flags & ObjectStreamConstants.SC_WRITE_METHOD) != 0; } - - // Returns true iff the class that this ObjectStreamClass represents - // has the following method: - // - // private void readObject (ObjectOutputStream) - // - // This method is used by the class to override default - // serialization behavior. - boolean hasReadMethod() - { - try - { - Class[] readObjectParams = { ObjectInputStream.class }; - forClass().getDeclaredMethod("readObject", readObjectParams); - return true; - } - catch (NoSuchMethodException e) - { - return false; - } - } - - // Returns true iff the class that this ObjectStreamClass represents // implements Serializable but does *not* implement Externalizable. boolean isSerializable() @@ -306,6 +285,8 @@ public class ObjectStreamClass implements Serializable { this.clazz = cl; + cacheMethods(); + long class_uid = getClassUID(cl); if (uid == 0) uid = class_uid; @@ -452,6 +433,50 @@ public class ObjectStreamClass implements Serializable fields[i].setOffset(objectFieldCount++); } + private Method findMethod(Method[] methods, String name, Class[] params, + Class returnType) + { +outer: + for(int i = 0; i < methods.length; i++) + { + if(methods[i].getName().equals(name) && + methods[i].getReturnType() == returnType) + { + Class[] mp = methods[i].getParameterTypes(); + if(mp.length == params.length) + { + for(int j = 0; j < mp.length; j++) + { + if(mp[j] != params[j]) + { + continue outer; + } + } + final Method m = methods[i]; + AccessController.doPrivileged(new PrivilegedAction() + { + public Object run() + { + m.setAccessible(true); + return null; + } + }); + return m; + } + } + } + return null; + } + + private void cacheMethods() + { + Method[] methods = forClass().getDeclaredMethods(); + readObjectMethod = findMethod(methods, "readObject", + new Class[] { ObjectInputStream.class }, + Void.TYPE); + readResolveMethod = findMethod(methods, "readResolve", + new Class[0], Object.class); + } private ObjectStreamClass(Class cl) { @@ -460,6 +485,7 @@ public class ObjectStreamClass implements Serializable isProxyClass = Proxy.isProxyClass(cl); clazz = cl; + cacheMethods(); name = cl.getName(); setFlags(cl); setFields(cl); @@ -508,9 +534,16 @@ public class ObjectStreamClass implements Serializable try { - Field serialPersistentFields = + final Field serialPersistentFields = cl.getDeclaredField("serialPersistentFields"); - serialPersistentFields.setAccessible(true); + AccessController.doPrivileged(new PrivilegedAction() + { + public Object run() + { + serialPersistentFields.setAccessible(true); + return null; + } + }); int modifiers = serialPersistentFields.getModifiers(); if (Modifier.isStatic(modifiers) @@ -553,12 +586,28 @@ public class ObjectStreamClass implements Serializable for (int from = 0, to = 0; from < all_fields.length; from++) if (all_fields[from] != null) { - Field f = all_fields[from]; - fields[to] = new ObjectStreamField(f.getName(), f.getType()); + final Field f = all_fields[from]; + AccessController.doPrivileged(new PrivilegedAction() + { + public Object run() + { + f.setAccessible(true); + return null; + } + }); + fields[to] = new ObjectStreamField(all_fields[from]); to++; } Arrays.sort(fields); + // Make sure we don't have any duplicate field names + // (Sun JDK 1.4.1. throws an Internal Error as well) + for (int i = 1; i < fields.length; i++) + { + if(fields[i - 1].getName().equals(fields[i].getName())) + throw new InternalError("Duplicate field " + + fields[i].getName() + " in class " + cl.getName()); + } calculateOffsets(); } @@ -571,8 +620,15 @@ public class ObjectStreamClass implements Serializable // 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 suid = cl.getDeclaredField("serialVersionUID"); - suid.setAccessible(true); + final Field suid = cl.getDeclaredField("serialVersionUID"); + AccessController.doPrivileged(new PrivilegedAction() + { + public Object run() + { + suid.setAccessible(true); + return null; + } + }); int modifiers = suid.getModifiers(); if (Modifier.isStatic(modifiers) @@ -769,6 +825,13 @@ public class ObjectStreamClass implements Serializable int primFieldSize = -1; // -1 if not yet calculated int objectFieldCount; + Method readObjectMethod; + Method readResolveMethod; + boolean realClassIsSerializable; + boolean realClassIsExternalizable; + ObjectStreamField[] fieldMapping; + Class firstNonSerializableParent; + boolean isProxyClass = false; // This is probably not necessary because this class is special cased already diff --git a/libjava/java/io/ObjectStreamField.java b/libjava/java/io/ObjectStreamField.java index cb2fdbc..603fe30 100644 --- a/libjava/java/io/ObjectStreamField.java +++ b/libjava/java/io/ObjectStreamField.java @@ -38,6 +38,8 @@ exception statement from your version. */ package java.io; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import gnu.java.lang.reflect.TypeSignature; /** @@ -54,6 +56,14 @@ public class ObjectStreamField implements Comparable private boolean unshared; private boolean persistent = false; private boolean toset = true; + private Field field; + + ObjectStreamField (Field field) + { + this (field.getName(), field.getType()); + this.field = field; + toset = !Modifier.isFinal(field.getModifiers()); + } /** * This constructor creates an ObjectStreamField instance @@ -105,7 +115,6 @@ public class ObjectStreamField implements Comparable } catch(ClassNotFoundException e) { - type = Object.class; //FIXME: ??? } } @@ -128,7 +137,6 @@ public class ObjectStreamField implements Comparable } catch(ClassNotFoundException e) { - type = Object.class; // ALSO FIXME } } @@ -176,7 +184,7 @@ public class ObjectStreamField implements Comparable public String getTypeString () { // use intern() - if (this.type.isPrimitive()) + if (isPrimitive()) return null; return typename.intern(); } @@ -225,7 +233,7 @@ public class ObjectStreamField implements Comparable */ public boolean isPrimitive () { - return type.isPrimitive (); + return typename.length() == 1; } public int compareTo (Object o) @@ -299,5 +307,112 @@ public class ObjectStreamField implements Comparable { return "ObjectStreamField< " + type + " " + name + " >"; } -} + final void setBooleanField(Object obj, boolean val) + { + try + { + field.setBoolean(obj, val); + } + catch(IllegalAccessException x) + { + throw new InternalError(x.getMessage()); + } + } + + final void setByteField(Object obj, byte val) + { + try + { + field.setByte(obj, val); + } + catch(IllegalAccessException x) + { + throw new InternalError(x.getMessage()); + } + } + + final void setCharField(Object obj, char val) + { + try + { + field.setChar(obj, val); + } + catch(IllegalAccessException x) + { + throw new InternalError(x.getMessage()); + } + } + + final void setShortField(Object obj, short val) + { + try + { + field.setShort(obj, val); + } + catch(IllegalAccessException x) + { + throw new InternalError(x.getMessage()); + } + } + + final void setIntField(Object obj, int val) + { + try + { + field.setInt(obj, val); + } + catch(IllegalAccessException x) + { + throw new InternalError(x.getMessage()); + } + } + + final void setLongField(Object obj, long val) + { + try + { + field.setLong(obj, val); + } + catch(IllegalAccessException x) + { + throw new InternalError(x.getMessage()); + } + } + + final void setFloatField(Object obj, float val) + { + try + { + field.setFloat(obj, val); + } + catch(IllegalAccessException x) + { + throw new InternalError(x.getMessage()); + } + } + + final void setDoubleField(Object obj, double val) + { + try + { + field.setDouble(obj, val); + } + catch(IllegalAccessException x) + { + throw new InternalError(x.getMessage()); + } + } + + final void setObjectField(Object obj, Object val) + { + try + { + field.set(obj, val); + } + catch(IllegalAccessException x) + { + throw new InternalError(x.getMessage()); + } + } +} |