FULL PRODUCT VERSION :
java version "1.6.0"
Java(TM) SE Runtime Environment (build 1.6.0-b105)
Java HotSpot(TM) Client VM (build 1.6.0-b105, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Windows XP
A DESCRIPTION OF THE PROBLEM :
ObjectInputStream throws a NullPointerException when deserializing an ArrayList of Externalizables if there is an IOException while deserializing one of these Externalizables.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the test case class.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
ois.readObject(); throws an IOException
ACTUAL -
ois.readObject(); throws a NullPointerException
java.lang.NullPointerException
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1820)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1719)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1305)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:348)
at NPEProvoker.main(NPEProvoker.java:28)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
public class NPEProvoker implements java.io.Externalizable {
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
throw new IOException(); //io exception for whatever reason
}
public void writeExternal(ObjectOutput out) throws IOException {
}
public static void main(String[] args){
try {
ArrayList<NPEProvoker> list = new ArrayList<NPEProvoker>();
list.add(new NPEProvoker());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(list);
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
ois.readObject();
} catch (IOException e) {
//expected result
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NullPointerException e){
//this happens
e.printStackTrace();
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
No workaround, but I guess the following could fix the problem:
Wrap the content of
private void ObjectInputStream.readExternalData(Externalizable obj, ObjectStreamClass desc)
with a try-catch block and execute
curContext = oldContext;
in a finally block in order to restore the old context of the stream even though an exception happened.