[jboss-jira] [JBoss JIRA] (JBSER-114) Object replacement and resolution doesn't conform to Java serialization
Ron Sigal (JIRA)
issues at jboss.org
Wed Jun 20 18:35:00 EDT 2018
[ https://issues.jboss.org/browse/JBSER-114?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Ron Sigal closed JBSER-114.
---------------------------
Resolution: Out of Date
> Object replacement and resolution doesn't conform to Java serialization
> -----------------------------------------------------------------------
>
> Key: JBSER-114
> URL: https://issues.jboss.org/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 was sent by Atlassian JIRA
(v7.5.0#75005)
More information about the jboss-jira
mailing list