Anjo is right, I was wrong. I thought, System.identityHashCode()
would be safe, at least when the objects are in 32 bit address space
and are not garbage collected during the process, but a simple test
turned out that this is wrong, probably due to the JVM memory
management shuffeling around the objects in memory. Using
System.identityHashCode(object) lowers the probability of the
problem, but it doesn't solve it.
One solution I could think to which should work would be to use an
IdentityHasMap inside of WOXMLCoder to keep track ofthe objects.
Timo
Am 04.07.2008 um 05:39 schrieb Anjo Krank:
Neither is OK. object.hashCode is not unique (can be a constant if
overridden) and System.identityHashCode is not unique either.
Cheers, Anjo
Am 03.07.2008 um 22:35 schrieb Timo Hoepfner:
FYI: I just filed this as rdar://6053207
Summary:
========
WOXMLCoder uses objectIDRef for mutable objects. IMHO it should
only use objectIDRefs, when it encounters an object with the same
System.identityHashCode(object) as a previously serialized object.
Currently it seems to rely on object.hashCode(), which is OK for
immutable objects, but not for mutable objects.
Steps to Reproduce:
===================
NSMutableArray a = new NSMutableArray();
NSMutableArray b = new NSMutableArray();
System.out.println("a: "+a);
System.out.println("b: "+b);
System.out.println("a==b? " + (a == b));
System.out.println("----------------------");
NSArray wrapper = new NSArray(new Object[] { a, b });
WOXMLCoder coder = WOXMLCoder.coder();
String s = coder.encodeRootObjectForKey(wrapper, "wrapper");
System.out.print(s);
System.out.println("----------------------");
WOXMLDecoder decoder = WOXMLDecoder.decoder();
NSArray deserializedWrapper = (NSArray) decoder.decodeRootObject
(new NSData(s.getBytes()));
NSMutableArray deserializedA = (NSMutableArray)
deserializedWrapper.objectAtIndex(0);
NSMutableArray deserializedB = (NSMutableArray)
deserializedWrapper.objectAtIndex(1);
System.out.println("deserializedA: " + deserializedA);
System.out.println("deserializedB: " + deserializedB);
System.out.println("deserializedA==deserializedB? " +
(deserializedA == deserializedB));
System.out.println("----------------------");
System.out.println("Adding 'foo' to 'a'");
deserializedA.addObject("foo");
System.out.println("Adding 'bar' to 'b'");
deserializedB.addObject("bar");
System.out.println("----------------------");
System.out.println("deserializedA: " + deserializedA);
System.out.println("deserializedB: " + deserializedB);
Actual Results:
===============
a: ()
b: ()
a==b? false
----------------------
<wrapper type="com.webobjects.foundation.NSArray" objectID="1">
<element type="com.webobjects.foundation.NSMutableArray"
objectID="2">
</element>
<element type="com.webobjects.foundation.NSMutableArray"
objectIDRef="2"></element>
</wrapper>
----------------------
deserializedA: ()
deserializedB: ()
deserializedA==deserializedB? true
----------------------
Adding 'foo' to 'a'
Adding 'bar' to 'b'
----------------------
deserializedA: ("foo", "bar")
deserializedB: ("foo", "bar")
Expected Results:
=================
deserializedA==deserializedB? false
Workarounds:
============
This subclass of WOXMLCoder hacks around the problem:
public class PDXMLCoder extends WOXMLCoder {
@SuppressWarnings("unchecked")
@Override
public void encodeObjectForKey(Object object, String s) {
if (object instanceof NSMutableArray) {
object = new _MutableArray((NSMutableArray) object);
}
else if (object instanceof NSMutableDictionary) {
object = new _MutableDictionary((NSMutableDictionary)
object);
}
else if (object instanceof NSMutableData) {
object = new _MutableData((NSMutableData) object);
}
super.encodeObjectForKey(object, s);
}
public PDXMLCoder() {
super();
}
public static WOXMLCoder coder() {
return new PDXMLCoder();
}
@SuppressWarnings("unchecked")
public static class _MutableArray extends NSMutableArray {
public _MutableArray() {
super();
}
public _MutableArray(NSArray array) {
super(array);
}
@Override
public Class classForCoder() {
return NSMutableArray.class;
}
@Override
public int hashCode() {
return System.identityHashCode(this);
}
}
@SuppressWarnings("unchecked")
public static class _MutableDictionary extends NSMutableDictionary {
public _MutableDictionary() {
super();
}
public _MutableDictionary(NSDictionary dict) {
super(dict);
}
@Override
public Class classForCoder() {
return NSMutableDictionary.class;
}
@Override
public int hashCode() {
return System.identityHashCode(this);
}
}
@SuppressWarnings("unchecked")
public static class _MutableData extends NSMutableData {
public _MutableData() {
super();
}
public _MutableData(NSMutableData data) {
super(data);
}
@Override
public Class classForCoder() {
return NSMutableData.class;
}
@Override
public int hashCode() {
return System.identityHashCode(this);
}
}
}
If you already have screwed serialized data, using this subclass
of WOXMLDecoder for deserializing can help in some situations:
public class PDXMLDecoder extends WOXMLDecoder {
@SuppressWarnings("unchecked")
@Override
public Object decodeObjectForKey(String s) {
Object object = super.decodeObjectForKey(s);
if (object instanceof NSMutableArray) {
NSMutableArray a = (NSMutableArray) object;
object = a.mutableClone();
}
else if (object instanceof NSMutableDictionary) {
NSMutableDictionary d = (NSMutableDictionary) object;
object = d.mutableClone();
}
else if (object instanceof NSMutableData) {
NSMutableData d = (NSMutableData) object;
object = d.clone();
}
return object;
}
public PDXMLDecoder() {
super();
}
public static WOXMLDecoder decoder(){
return new PDXMLDecoder();
}
}
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/krank%
40logicunited.com
This email sent to [EMAIL PROTECTED]
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com
This email sent to [EMAIL PROTECTED]