Relates :
|
|
Relates :
|
|
Relates :
|
FULL PRODUCT VERSION : java version "1.4.2_04" Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_04-b05) Java HotSpot(TM) Client VM (build 1.4.2_04-b05, mixed mode) ADDITIONAL OS VERSION INFORMATION : Microsoft Windows 2000 [Version 5.00.2195] A DESCRIPTION OF THE PROBLEM : De-serializing an instance of this class throws a NullPointerException: import java.io.*; import java.util.*; private class MyClass implements Serializable { private String m_name = "anything"; private Set m_set = new HashSet (); public MyClass () { m_set.add (this); } public int hashCode () { return m_name.hashCode (); } } I think this happens because the VM attempts to de-serialize m_set first and in doing so calls hashCode() on each of its members. However, the instance of MyClass, contained in m_set, has not yet been fully de-serialized since this involves de-serializing m_set first. Thus, m_name is still null when hashCode() is called, causing the Exception. STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : Serialize and then De-serialize an instance of MyClass using the program provided. EXPECTED VERSUS ACTUAL BEHAVIOR : EXPECTED - I was expecting to see MyClass De-serialize completely and wihout error. ACTUAL - A NullPointerException was thrown from the line: return m_name.hashCode (); m_name was null. ERROR MESSAGES/STACK TRACES THAT OCCUR : java.lang.NullPointerException at com.bentley.test.MyClass.hashCode(TestSerialization.java:67) at java.util.HashMap.hash(HashMap.java:261) at java.util.HashMap.put(HashMap.java:379) at java.util.HashSet.readObject(HashSet.java:277) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:324) at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:838) at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1746) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1646) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1274) at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1845) at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1769) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1646) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1274) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:324) at com.bentley.test.TestSerialization.input(TestSerialization.java:46) at com.bentley.test.TestSerialization.main(TestSerialization.java:23) Exception in thread "main" REPRODUCIBILITY : This bug can be reproduced always. ---------- BEGIN SOURCE ---------- /*--------------------------------------------------------------------------------------+ | | $RCSfile: TestSerialization.java,v $ | $Revision: 1.0 $ | $Date: 2004/08/24 14:31:30 $ | | $Copyright: (c) 2004 Bentley Systems, Incorporated. All rights reserved. $ | +--------------------------------------------------------------------------------------*/ package com.bentley.test; import java.io.*; import java.util.*; public class TestSerialization { public static void main (String[] args) throws Exception { MyClass obj = new MyClass (); byte[] serialized = output (obj); Serializable deserialized = input (serialized); } public static byte[] output (Serializable obj) throws Exception { ByteArrayOutputStream obytes = new ByteArrayOutputStream (); ObjectOutputStream ostream = new ObjectOutputStream (obytes); ostream.writeObject (obj); ostream.flush (); byte[] bytes = obytes.toByteArray (); obytes.close (); ostream.close (); return bytes; } public static Serializable input (byte[] bytes) throws Exception { ByteArrayInputStream ibytes = new ByteArrayInputStream (bytes); ObjectInputStream istream = new ObjectInputStream (ibytes); Serializable obj = (Serializable)istream.readObject (); ibytes.close (); istream.close (); return obj; } } class MyClass implements Serializable { private String m_name = "anything"; private Set m_set = new HashSet (); public MyClass () { m_set.add (this); } public int hashCode () { return m_name.hashCode (); } } ---------- END SOURCE ---------- CUSTOMER SUBMITTED WORKAROUND : I have not found a good one yet, other than to avoid overriding the hashCode method. ###@###.### 2004-12-14 10:26:52 GMT
|