Serialization patch and question

Jose Orlando Pereira jop at di.uminho.pt
Wed Feb 3 07:48:01 PST 1999


Hi,

I've had some trouble with serialization on Kaffe (multiple refereces to
the same object, self referencing structures and readObject methods).
I've enclosed a patch that corrects all these problems and makes serialization
in Kaffe (almost) work for me.

A fourth problem (which produces "interesting" bugs) is exposed by
the enclosed program. In short, serialization incorrectly aliases
references because it uses a standard Hashtable, thus using equals()
and not ==.

As a side effect, there is a performance penalty in using hashCode()
and equals() instead of using directly the memory address, i.e.,
as default hashCode() and equals() methods for java.lang.Object do.

Before I start working on this, is there any chance of using default
Object.equals() and Object.hashCode() methods on an object of a derived
class, which redefines them as something else, besides "going native"?

Thanks in advance,

-- 
Jose Orlando Pereira
* mailto:jop at di.uminho.pt * http://gsd.di.uminho.pt/~jop *
-------------- next part --------------
diff -ru kaffe-snap/libraries/javalib/java/io/ObjectInputStream.java kaffe-snap-jop/libraries/javalib/java/io/ObjectInputStream.java
--- kaffe-snap/libraries/javalib/java/io/ObjectInputStream.java	Wed Dec  9 23:20:11 1998
+++ kaffe-snap-jop/libraries/javalib/java/io/ObjectInputStream.java	Tue Feb  2 18:39:06 1999
@@ -209,6 +209,8 @@
 					throw new StreamCorruptedException("expected class desc");
 				}
 				currObject = allocateNewObject(currStreamClass.clazz, null);
+				Integer key = new Integer(++nextKey);
+				objectsDone.put(key, currObject);
 				if ((currStreamClass.method & ObjectStreamConstants.SC_EXTERNALIZABLE) != 0) {
                                         try {
                                                 ((Externalizable)currObject).readExternal(this);
@@ -217,7 +219,7 @@
                                         }
 				}
 				else if ((currStreamClass.method & ObjectStreamConstants.SC_WRRD_METHODS) != 0) {
-					invokeObjectReader(currObject, ObjectStreamClass.class);
+					invokeObjectReader(currObject, currObject.getClass());
 				}
 				else if ((currStreamClass.method & ObjectStreamConstants.SC_SERIALIZABLE) != 0) {
 					defaultReadObject();
@@ -240,6 +242,8 @@
 			case ObjectStreamConstants.TC_CLASSDESC:
 				ObjectStreamClass cls = new ObjectStreamClass();
 				currObject = (Object)cls;
+				Integer key = new Integer(++nextKey);
+				objectsDone.put(key, currObject);
 				invokeObjectReader(currObject, ObjectStreamClass.class);
 				cls.clazz = resolveClass(cls);
 				cls.buildFieldsAndOffset();
@@ -247,6 +251,8 @@
 
 			case ObjectStreamConstants.TC_STRING:
 				currObject = readUTF();
+				Integer key = new Integer(++nextKey);
+				objectsDone.put(key, currObject);
 				break;
 
 			case ObjectStreamConstants.TC_RESET:
@@ -259,10 +265,6 @@
 			default:
 				throw new StreamCorruptedException("unexpected token: " + tok);
 			}
-
-			// Insert into hash table.
-			Integer key = new Integer(++nextKey);
-			objectsDone.put(currObject, key);
 		}
 
 		Object obj = currObject;
@@ -312,6 +314,8 @@
 {
 	int len = readInt();
 	Object obj = allocateNewArray(currStreamClass.clazz, len);
+	Integer key = new Integer(++nextKey);
+	objectsDone.put(key, obj);
 	Class elem = currStreamClass.clazz.getComponentType();
 
 	if (elem == Object.class) {
-------------- next part --------------
// Demonstrates Serialization aliasing bug

import java.io.*;

class Pt implements Serializable {
	public Pt(int x, int y) {
		this.x=x;
		this.y=y;
	}

	public void move(int dx, int dy) {
		x+=dx;
		y+=dy;
	}

	public boolean equals(Object obj) {
		if (!(obj instanceof Pt))
			return false;
		Pt other=(Pt)obj;
		return x==other.x && y==other.y;
	}

	public int hashCode() {
		return x+y;
	}

	public String toString() {
		return "("+x+", "+y+")";
	}

	private int x, y;
};

class Rect implements Serializable {
	private Pt corner1, corner2;

	public Rect(int x1, int y1, int x2, int y2) {
		corner1=new Pt(x1, y1);
		corner2=new Pt(x2, y2);
	}

	public void move(int dx, int dy) {
		corner1.move(dx, dy);
		corner2.move(dx, dy);
	}

	public String toString() {
		return corner1.toString()+"-"+corner2;
	}
}

public class Alias {
	public static void main(String args[]) {
		try {
			Rect rect1=new Rect(1,1,1,1);
			ByteArrayOutputStream baos=new ByteArrayOutputStream();
			ObjectOutputStream oos=new ObjectOutputStream(baos);
			oos.writeObject(rect1);
			oos.flush();
			byte data[]=baos.toByteArray();
			System.out.println("Tam: "+data.length);
			ByteArrayInputStream bais=new ByteArrayInputStream(data);
			ObjectInputStream ois=new ObjectInputStream(bais);
			Rect rect2=(Rect)ois.readObject();
			System.out.println("rect1="+rect1+" rect2="+rect2);
			rect1.move(2,2);
			rect2.move(2,2);
			System.out.println("rect1="+rect1+" rect2="+rect2);
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
};



More information about the kaffe mailing list