-
Bug
-
Resolution: Won't Fix
-
P4
-
None
-
6u29
-
x86
-
windows_2003
FULL PRODUCT VERSION :
java version "1.6.0_27"
Java(TM) SE Runtime Environment (build 1.6.0_27-b07)
Java HotSpot(TM) Client VM (build 20.2-b06, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
Windows 2008 Server x64
A DESCRIPTION OF THE PROBLEM :
I have received the following exception in an application that serializes objects over RMI
java.lang.IllegalStateException: unread block data
at java.io.ObjectInputStream$BlockDataInputStream.setBlockDataMode(ObjectInputStream.java:2376)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1360)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
at sun.rmi.server.UnicastRef.unmarshalValue(UnicastRef.java:306)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:155)
at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:178)
at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:132)
By debugging the serialization code I found out that the real cause (in this case a RuntimeException) is masked out due to a bad exception handling in ObjectInputStream.readObject0(). What happens is that the call to readOrdinaryObject in line 1328:
case TC_OBJECT:
return checkResolve(readOrdinaryObject(unshared));
eventually calls ObjectStreamClass.invokeReadObjectNoData() which catches an InvocationTargetException and then calls throwMiscException on the cause. This method then in turn throws that exception. The problem now is that in ObjectInputStream.readObject0() there is a finally block:
// ...
} finally {
depth--;
bin.setBlockDataMode(oldMode);
}
and that the call to ObjectInputStream.setBlockDataMode() also throws an exception because there is still data available (of course, there was an exception that aborted the deserialization!). As a consequence the original RuntimeException that contains the actual reason for the problem is gone!
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Should be reproducible by implementing readObject() on any Serializable class like that:
private void readObject(ObjectInputStream is) throws IOException
{
throw new RuntimeException("I will get masked out!");
}
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I expect to receive the original cause and not the "java.lang.IllegalStateException: unread block data".
ACTUAL -
Already described above.
REPRODUCIBILITY :
This bug can be reproduced always.
java version "1.6.0_27"
Java(TM) SE Runtime Environment (build 1.6.0_27-b07)
Java HotSpot(TM) Client VM (build 20.2-b06, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
Windows 2008 Server x64
A DESCRIPTION OF THE PROBLEM :
I have received the following exception in an application that serializes objects over RMI
java.lang.IllegalStateException: unread block data
at java.io.ObjectInputStream$BlockDataInputStream.setBlockDataMode(ObjectInputStream.java:2376)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1360)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
at sun.rmi.server.UnicastRef.unmarshalValue(UnicastRef.java:306)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:155)
at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:178)
at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:132)
By debugging the serialization code I found out that the real cause (in this case a RuntimeException) is masked out due to a bad exception handling in ObjectInputStream.readObject0(). What happens is that the call to readOrdinaryObject in line 1328:
case TC_OBJECT:
return checkResolve(readOrdinaryObject(unshared));
eventually calls ObjectStreamClass.invokeReadObjectNoData() which catches an InvocationTargetException and then calls throwMiscException on the cause. This method then in turn throws that exception. The problem now is that in ObjectInputStream.readObject0() there is a finally block:
// ...
} finally {
depth--;
bin.setBlockDataMode(oldMode);
}
and that the call to ObjectInputStream.setBlockDataMode() also throws an exception because there is still data available (of course, there was an exception that aborted the deserialization!). As a consequence the original RuntimeException that contains the actual reason for the problem is gone!
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Should be reproducible by implementing readObject() on any Serializable class like that:
private void readObject(ObjectInputStream is) throws IOException
{
throw new RuntimeException("I will get masked out!");
}
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I expect to receive the original cause and not the "java.lang.IllegalStateException: unread block data".
ACTUAL -
Already described above.
REPRODUCIBILITY :
This bug can be reproduced always.
- relates to
-
JDK-7172206 ObjectInputStream can swallow exceptions
-
- Open
-