]
Ron Sigal updated JBSER-114:
----------------------------
Attachment: ClebertOutputSample.java
I've attached a program which demonstrates the difference between JBossSerialization
and Java serialization on the output side. The output is
entering testJavaSerialization
ClebertOutputSample$TestSerializableWithWriteReplace1(a)e89b94.writeReplace() ->
ClebertOutputSample$TestSerializableWithWriteReplace2@1bf73fa
ClebertOutputSample$TestSerializableWithWriteReplace2(a)1bf73fa.writeReplace() ->
ClebertOutputSample$TestSerializableWithWriteReplace3@1cf8583
ClebertOutputSample$TestSerializableWithWriteReplace3(a)1cf8583.writeReplace() (no
replacement)
ClebertOutputSample$TestJavaObjectOutputStream@665753.replaceObject(ClebertOutputSample$TestSerializableWithWriteReplace3(a)1cf8583)
->ClebertOutputSample$TestSerializableWithWriteReplace4@ef22f8
entering testJBossSerialization
ClebertOutputSample$TestSerializableWithWriteReplace1(a)3ee284.writeReplace() ->
ClebertOutputSample$TestSerializableWithWriteReplace2@8965fb
ClebertOutputSample$TestSerializableWithWriteReplace2(a)8965fb.writeReplace() ->
ClebertOutputSample$TestSerializableWithWriteReplace3@fa3ac1
ClebertOutputSample$TestSerializableWithWriteReplace3(a)fa3ac1.writeReplace() (no
replacement)
ClebertOutputSample$TestJBossObjectOutputStream@e86da0.replaceObject(ClebertOutputSample$TestSerializableWithWriteReplace3(a)fa3ac1)
-> ClebertOutputSample$TestSerializableWithWriteReplace4@1754ad2
ClebertOutputSample$TestJBossObjectOutputStream@e86da0.replaceObject(ClebertOutputSample$TestSerializableWithWriteReplace4(a)1754ad2)
-> ClebertOutputSample$TestSerializableWithWriteReplace5@fe64b9
Object replacement and resolution doesn't conform to Java
serialization
-----------------------------------------------------------------------
Key: JBSER-114
URL:
https://jira.jboss.org/jira/browse/JBSER-114
Project: JBoss Serialization
Issue Type: Bug
Affects Versions: 1.0.3 GA
Reporter: Ron Sigal
Assignee: Ron Sigal
Fix For: 1.1.0 Beta
Attachments: ClebertOutputSample.java
There are two ways in which object replacement and resolution in JBossSerialization
doesn't conform to Java serialization.
This discussion applies to JBossSerialization as it currently exists on trunk.
===============================================================================
First divergence.
According to Section 3 "Object Input Classes"
(
http://java.sun.com/javase/6/docs/platform/serialization/spec/input.html) of the Java
Object Serialization Specification, the sequence of replacements while writing an object
is:
1. if the class has a writeReplace() method, that method is called, and then
2. if replacement has been enabled by calling ObjectOutputStream.enableReplaceObject(),
then ObjectOutputStream.replaceObject() is called.
[NOTE that the implementation in java.io.ObjectOutputStream.writeObject0() doesn't
seem to conform to the above algorithm:
for (;;) {
// REMIND: skip this check for strings/arrays?
Class repCl;
desc = ObjectStreamClass.lookup(cl, true);
if (!desc.hasWriteReplaceMethod() ||
(obj = desc.invokeWriteReplace(obj)) == null ||
(repCl = obj.getClass()) == cl)
{
break;
}
cl = repCl;
}
if (enableReplace) {
Object rep = replaceObject(obj);
if (rep != obj && rep != null) {
cl = rep.getClass();
desc = ObjectStreamClass.lookup(cl, true);
}
obj = rep;
}
In particular, the for loop seems to be divergent from the semantics.]
On the other hand, JBossSerialization does the following:
1. if replacement has been enabled, call ObjectOutputStream.replaceObject() [In
DataContainer.DataContainerDirectOutput.writeObject()]
2. if the class has a writeReplace() method then keep applying writeReplace() until it
returns either (1) null, (2) the object to which it was applied, (3) an object of the
same class as the object to which it was applied, or (4) an immutable value. If (1) or
(4), write new value and return.
3. if replacement has been enabled, call ObjectOutputStream.replaceObject().
4. *GOTO* 2.
While reading an object in Java serialization, the sequence of replacements is
1. if the class has a readResolve() method, that method is called, and then
2. if replacement has been enabled by calling ObjectInputStream.enableResolveObject(),
then ObjectInputStream.resolveObject () is called.
On the other hand, JBossSerialization does the following:
1. if replacement has been enabled by calling ObjectInputStream.enableResolveObject(),
then ObjectInputStream.resolveObject () is called.
2. if the class has a readResolve() method, that method is called, and then
3. if replacement has been enabled by calling ObjectInputStream.enableResolveObject(),
then ObjectInputStream.resolveObject () is called.
===============================================================================
Second divergence.
The Java serialization spec gives the following steps in serialization:
4. If the object has been previously replaced, as described in Step 8, write the
handle of the replacement to the stream and writeObject() returns.
...
8. a. ....
b. ...
If the original object was replaced by either one or both steps above, the
mapping from the original object to the replacement is recorded for later use in Step 4.
Then, Steps 3 through 7 are repeated on the new object.
But JBossSerialization does this:
* Apply all the replacements
* If the replacement object has already been written, write its "handle".
The following test will fail in JBossSerialization:
ArrayList<Object> testList = new ArrayList<Object>();
testList = Collections.unmodifiableList(testList);
marshaller.writeObject(testList);
marshaller.writeObject(testList);
assertSame(unmarshaller.readObject(), unmarshaller.readObject());
The assertion will fail because Collections.unmodifiableList() returns an instance of
static class UnmodifiableRandomAccessList<E> extends UnmodifiableList<E>
implements RandomAccess {
private Object writeReplace() {
return new UnmodifiableList<E>(list);
}
}
JBossSerialization applies UnmodifiableRandomAccessList.writeReplace() during each call
to marshaller.writeObject(), so two different copies of testList get written. But in Java
serialization, the second call would see that the object has already been written and a
handle would get written.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: