ObjectInputStream.java: Made all calls to dumpElement[ln] conditional on dump flag.
authorJeroen Frijters <jeroen@frijters.net>
Fri, 6 Feb 2004 13:27:36 +0000 (13:27 +0000)
committerMichael Koch <mkoch@gcc.gnu.org>
Fri, 6 Feb 2004 13:27:36 +0000 (13:27 +0000)
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

libjava/ChangeLog
libjava/java/io/ObjectInputStream.java
libjava/java/io/ObjectStreamClass.java
libjava/java/io/ObjectStreamField.java

index fd25156..204cd71 100644 (file)
@@ -1,3 +1,31 @@
+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.
+
 2004-02-05  Thomas Fitzsimmons  <fitzsim@redhat.com>
 
        * java/awt/Component.java (getFont): Return a default font
index a277691..d0def09 100644 (file)
@@ -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
index 5bd0e68..429db18 100644 (file)
@@ -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
index cb2fdbc..603fe30 100644 (file)
@@ -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());
+      }
+  }
+}