diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 947bf15439e6b36d56eff8b846a41fe1d6313c9e..b46441a5dd475f583bd95003ec0f26fdda7358bc 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,3 +1,16 @@
+2004-02-28  Guilhem Lavaux <guilhem@kaffe.org>
+
+	* java/io/ObjectInputStream.java
+	(readClassDescriptor): Keep elements of the mapping non null.
+	(checkTypeConsistency): New method.
+	(readFields): Fixed main loop and base logic. Small reindentation.
+	* java/io/ObjectStreamField.java
+	(lookupField): New method to update the field reference.
+	(checkFieldType): New method.
+	* java/io/ObjectStreamClass.java
+	(setClass, setFields): Call lookupField when building the field
+	database. Check the real field type.
+
 2004-02-28  Michael Koch  <konqueror@gmx.de>
 
 	* java/nio/ByteOrder.java
diff --git a/libjava/java/io/ObjectInputStream.java b/libjava/java/io/ObjectInputStream.java
index ce2d0ca90e26f10bc0e882413b11a4d620ab0a4e..3c2dec97010d534f8c6010558a31c172e67fce21 100644
--- a/libjava/java/io/ObjectInputStream.java
+++ b/libjava/java/io/ObjectInputStream.java
@@ -1,6 +1,5 @@
 /* ObjectInputStream.java -- Class used to read serialized objects
-   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
-   Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -412,6 +411,64 @@ public class ObjectInputStream extends InputStream
     return ret_val;
   }
 
+  /**
+   * This method makes a partial check of types for the fields
+   * contained given in arguments. It checks primitive types of
+   * fields1 against non primitive types of fields2. This method 
+   * assumes the two lists has already been sorted according to 
+   * the Java specification.
+   *
+   * @param name Name of the class owning the given fields.
+   * @param fields1 First list to check.
+   * @param fields2 Second list to check.
+   * @throws InvalidClassException if a field in fields1, which has a primitive type, is a present
+   * in the non primitive part in fields2.
+   */
+  private void checkTypeConsistency(String name, ObjectStreamField[] fields1, ObjectStreamField[] fields2)
+    throws InvalidClassException
+    int nonPrimitive = 0;
+    
+    for (nonPrimitive = 0; 
+	 nonPrimitive < fields1.length
+	   && fields1[nonPrimitive].isPrimitive(); nonPrimitive++)
+      {
+      }
+
+    if (nonPrimitive == fields1.length)
+      return;
+    
+    int i = 0;
+    ObjectStreamField f1;
+    ObjectStreamField f2;
+    
+    while (i < fields2.length
+	   && nonPrimitive < fields1.length)
+      {
+	f1 = fields1[nonPrimitive];
+	f2 = fields2[i];
+	
+	if (!f2.isPrimitive())
+	  break;
+
+	int compVal = f1.getName().compareTo (f2.getName());
+
+	if (compVal < 0)
+	  {
+	    nonPrimitive++;
+	  }
+	else if (compVal > 0)
+	  {
+	    i++;
+	  }
+	else
+	  {
+	    throw new InvalidClassException
+	      ("invalid field type for " + f2.getName() +
+	       " in class " + name);
+	  }
+      }
+  }
+
   /**
    * This method reads a class descriptor from the real input stream
    * and use these data to create a new instance of ObjectStreamClass.
@@ -497,6 +554,15 @@ public class ObjectInputStream extends InputStream
     int real_idx = 0;
     int map_idx = 0;
 
+    /*
+     * Check that there is no type inconsistencies between the lists.
+     * A special checking must be done for the two groups: primitive types and
+     * not primitive types. 
+     */
+    checkTypeConsistency(name, real_fields, stream_fields);
+    checkTypeConsistency(name, stream_fields, real_fields);
+
+    
     while (stream_idx < stream_fields.length
 	   || real_idx < real_fields.length)
       {
@@ -514,7 +580,7 @@ public class ObjectInputStream extends InputStream
 	else
 	  {
 	    int comp_val =
-		real_fields[real_idx].compareTo (stream_fields[stream_idx]);
+	      real_fields[real_idx].compareTo (stream_fields[stream_idx]);
 
 	    if (comp_val < 0)
 	      {
@@ -528,21 +594,13 @@ public class ObjectInputStream extends InputStream
 	      {
 		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.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;
+
 	/* If some of stream_fields does not correspond to any of real_fields,
 	 * or the opposite, then fieldmapping will go short.
 	 */
@@ -551,7 +609,7 @@ public class ObjectInputStream extends InputStream
 	    ObjectStreamField[] newfieldmapping =
 	      new ObjectStreamField[fieldmapping.length + 2];
 	    System.arraycopy(fieldmapping, 0,
-	      newfieldmapping, 0, fieldmapping.length);
+			     newfieldmapping, 0, fieldmapping.length);
 	    fieldmapping = newfieldmapping;
 	  }
 	fieldmapping[map_idx++] = stream_field;
@@ -1577,121 +1635,119 @@ public class ObjectInputStream extends InputStream
       {
 	ObjectStreamField stream_field = fields[i];
 	ObjectStreamField real_field = fields[i + 1];
-	if(stream_field != null || real_field != null)
-	  {
-	    boolean read_value = stream_field != null;
-	    boolean set_value = real_field != null;
-	    String field_name;
-	    char type;
-	    if (stream_field != null)
-	      {
-		field_name = stream_field.getName();
-		type = stream_field.getTypeCode();
-	      }
-	    else
-	      {
-		field_name = real_field.getName();
-		type = real_field.getTypeCode();
-	      }
+	boolean read_value = (stream_field != null && stream_field.getOffset() >= 0 && stream_field.isToSet());
+	boolean set_value = (real_field != null && real_field.isToSet());
+	String field_name;
+	char type;
 
-	    switch(type)
-	      {
-		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);
-	      }
+	if (stream_field != null)
+	  {
+	    field_name = stream_field.getName();
+	    type = stream_field.getTypeCode();
+	  }
+	else
+	  {
+	    field_name = real_field.getName();
+	    type = real_field.getTypeCode();
+	  }
+	
+	switch(type)
+	  {
+	  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);
 	  }
       }
   }
-
+  
   // Toggles writing primitive data to block-data buffer.
   private boolean setBlockDataMode (boolean on)
   {
diff --git a/libjava/java/io/ObjectStreamClass.java b/libjava/java/io/ObjectStreamClass.java
index 429db187b4752805f859c045c43be289c9348051..d080f280ba907a591ba9a6bd612b69066ec1c032 100644
--- a/libjava/java/io/ObjectStreamClass.java
+++ b/libjava/java/io/ObjectStreamClass.java
@@ -327,7 +327,7 @@ public class ObjectStreamClass implements Serializable
 	i = 0; j = 0; k = 0;
 	while (i < fields.length && j < exportedFields.length)
 	  {
-	    int comp = fields[i].getName().compareTo(exportedFields[j].getName());
+	    int comp = fields[i].compareTo(exportedFields[j]);
 
 	    if (comp < 0)
 	      {
@@ -344,10 +344,27 @@ public class ObjectStreamClass implements Serializable
 		newFieldList[k] = exportedFields[j];
 		newFieldList[k].setPersistent(true);
 		newFieldList[k].setToSet(false);
+		try
+		  {
+		    newFieldList[k].lookupField(clazz);
+		    newFieldList[k].checkFieldType();
+		  }
+		catch (NoSuchFieldException _)
+		  {
+		  }
 		j++;
 	      }
 	    else
 	      {
+		try
+		  {
+		    exportedFields[j].lookupField(clazz);
+		    exportedFields[j].checkFieldType();
+		  }
+		catch (NoSuchFieldException _)
+		  {
+		  }
+
 		if (!fields[i].getType().equals(exportedFields[j].getType()))
 		  throw new InvalidClassException
 		    ("serialPersistentFields must be compatible with" +
@@ -554,6 +571,19 @@ outer:
 	    if (fields != null)
 	      {
 		Arrays.sort (fields);
+		// Retrieve field reference.
+		for (int i=0; i < fields.length; i++)
+		  {
+		    try
+		      {
+			fields[i].lookupField(cl);
+		      }
+		    catch (NoSuchFieldException _)
+		      {
+			fields[i].setToSet(false);
+		      }
+		  }
+		
 		calculateOffsets();
 		return;
 	      }
@@ -798,7 +828,7 @@ outer:
 
     fieldsArray = new ObjectStreamField[ o.length ];
     System.arraycopy(o, 0, fieldsArray, 0, o.length);
-    
+
     return fieldsArray;
   }
 
diff --git a/libjava/java/io/ObjectStreamField.java b/libjava/java/io/ObjectStreamField.java
index 603fe30917d2581978edc414739a8d10f8d73fe0..f4a866ed06753867b6e87a9b4998181aeff37fc0 100644
--- a/libjava/java/io/ObjectStreamField.java
+++ b/libjava/java/io/ObjectStreamField.java
@@ -41,6 +41,8 @@ package java.io;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
 import gnu.java.lang.reflect.TypeSignature;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 
 /**
  * This class intends to describe the field of a class for the serialization
@@ -99,7 +101,7 @@ public class ObjectStreamField implements Comparable
  
   /**
    * There are many cases you can not get java.lang.Class from typename 
-   * if your context class loader cann not load it, then use typename to
+   * if your context class loader cannot load it, then use typename to
    * construct the field.
    *
    * @param name Name of the field to export.
@@ -292,7 +294,7 @@ public class ObjectStreamField implements Comparable
   }
 
   /**
-   * This methods returns true if the field is marked as to be
+   * This method returns true if the field is marked as to be
    * set.
    *
    * @return True if it is to be set, false in the other cases.
@@ -303,6 +305,49 @@ public class ObjectStreamField implements Comparable
     return toset;
   }
 
+  /**
+   * This method searches for its field reference in the specified class
+   * object. It requests privileges. If an error occurs the internal field
+   * reference is not modified.
+   *
+   * @throws NoSuchFieldException if the field name does not exist in this class.
+   * @throws SecurityException if there was an error requesting the privileges.
+   */
+  void lookupField(Class clazz) throws NoSuchFieldException, SecurityException
+  {
+    final Field f = clazz.getDeclaredField(name);
+    
+    AccessController.doPrivileged(new PrivilegedAction()
+      {
+	public Object run()
+	{
+	  f.setAccessible(true);
+	  return null;
+	}
+      });
+    
+    this.field = f;
+  }
+
+  /**
+   * This method check whether the field described by this
+   * instance of ObjectStreamField is compatible with the
+   * actual implementation of this field.
+   *
+   * @throws NullPointerException if this field does not exist
+   * in the real class.
+   * @throws InvalidClassException if the types are incompatible.
+   */
+  void checkFieldType() throws InvalidClassException
+  {
+    Class ftype = field.getType();
+
+    if (!ftype.isAssignableFrom(type))
+      throw new InvalidClassException
+	("invalid field type for " + name +
+	 " in class " + field.getDeclaringClass());
+  }
+
   public String toString ()
   {
     return "ObjectStreamField< " + type + " " + name + " >";
@@ -310,102 +355,102 @@ public class ObjectStreamField implements Comparable
 
   final void setBooleanField(Object obj, boolean val)
   {
-      try
+    try
       {
-	  field.setBoolean(obj, val);
+	field.setBoolean(obj, val);
       }
-      catch(IllegalAccessException x)
+    catch(IllegalAccessException x)
       {
-	  throw new InternalError(x.getMessage());
+	throw new InternalError(x.getMessage());
       }
   }
-
+  
   final void setByteField(Object obj, byte val)
   {
-      try
+    try
       {
-	  field.setByte(obj, val);
+	field.setByte(obj, val);
       }
-      catch(IllegalAccessException x)
+    catch(IllegalAccessException x)
       {
-	  throw new InternalError(x.getMessage());
+	throw new InternalError(x.getMessage());
       }
   }
-
+  
   final void setCharField(Object obj, char val)
   {
-      try
+    try
       {
-	  field.setChar(obj, val);
+	field.setChar(obj, val);
       }
-      catch(IllegalAccessException x)
+    catch(IllegalAccessException x)
       {
-	  throw new InternalError(x.getMessage());
+	throw new InternalError(x.getMessage());
       }
   }
-
+  
   final void setShortField(Object obj, short val)
   {
-      try
+    try
       {
-	  field.setShort(obj, val);
+	field.setShort(obj, val);
       }
-      catch(IllegalAccessException x)
+    catch(IllegalAccessException x)
       {
-	  throw new InternalError(x.getMessage());
+	throw new InternalError(x.getMessage());
       }
   }
-
+  
   final void setIntField(Object obj, int val)
   {
-      try
+    try
       {
-	  field.setInt(obj, val);
+	field.setInt(obj, val);
       }
-      catch(IllegalAccessException x)
+    catch(IllegalAccessException x)
       {
-	  throw new InternalError(x.getMessage());
+	throw new InternalError(x.getMessage());
       }
   }
-
+  
   final void setLongField(Object obj, long val)
   {
-      try
+    try
       {
-	  field.setLong(obj, val);
+	field.setLong(obj, val);
       }
-      catch(IllegalAccessException x)
+    catch(IllegalAccessException x)
       {
-	  throw new InternalError(x.getMessage());
+	throw new InternalError(x.getMessage());
       }
   }
-
+  
   final void setFloatField(Object obj, float val)
   {
-      try
+    try
       {
-	  field.setFloat(obj, val);
+	field.setFloat(obj, val);
       }
-      catch(IllegalAccessException x)
+    catch(IllegalAccessException x)
       {
-	  throw new InternalError(x.getMessage());
+	throw new InternalError(x.getMessage());
       }
   }
-
+  
   final void setDoubleField(Object obj, double val)
   {
-      try
+    try
       {
-	  field.setDouble(obj, val);
+	field.setDouble(obj, val);
       }
-      catch(IllegalAccessException x)
+    catch(IllegalAccessException x)
       {
-	  throw new InternalError(x.getMessage());
+	throw new InternalError(x.getMessage());
       }
   }
-
+  
   final void setObjectField(Object obj, Object val)
-  {
+  { 
     try
       {
 	field.set(obj, val);