You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@geode.apache.org by "Bruce Schuchardt (JIRA)" <ji...@apache.org> on 2016/11/18 17:59:58 UTC

[jira] [Updated] (GEODE-2130) Serialized data generated by DataSerializer.writeObject depends on the type of OutputStream

     [ https://issues.apache.org/jira/browse/GEODE-2130?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Bruce Schuchardt updated GEODE-2130:
------------------------------------
    Description: 
I hit this with a simple test using DataSerializer to write and read a java Serializable object.

The problem I'm seeing is that there is a difference in the serialized form of an object depending on whether DataSerializer is passed an ObjectInputStream or just a DataInputStream.

With ObjectInputStream DataSerializer.writeObject just calls writeObject on the underlying ObjectInputStream. With DataInputStream, DataSerializer constructs a new ObjectInputStream.

The problem is that the constructor for ObjectOutputStream actually writes two shorts to the stream. So the serialized form may or may not include those two shorts.

DataSerializer.readObject expects to read those two shorts, because it constructs a DSObjectInputStream unless the input is already a DSObjectInputStream.

Because of that, just writing and reading an object and result in an EOFException:
{noformat}
java.io.EOFException
	at java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2353)
	at java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:2822)
	at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:804)
	at java.io.ObjectInputStream.<init>(ObjectInputStream.java:301)
	at org.apache.geode.internal.InternalDataSerializer$DSObjectInputStream.<init>(InternalDataSerializer.java:3583)
	at org.apache.geode.internal.InternalDataSerializer.basicReadObject(InternalDataSerializer.java:2988)
	at org.apache.geode.DataSerializer.readObject(DataSerializer.java:3281)
	at DataSerializerJUnitTest.test(DataSerializerJUnitTest.java:20)
{noformat}

Here's a simple test of this issue:
{code}
import org.apache.geode.DataSerializer;
import org.junit.Test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class DataSerializerJUnitTest {

  @Test
  public void test() throws IOException, ClassNotFoundException {
    final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    ObjectOutputStream out = new ObjectOutputStream(byteArrayOutputStream);
    DataSerializer.writeObject(new MyObject(), out);
    out.close();
    ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
    final Object object = DataSerializer.readObject(in);
  }

  private static class MyObject implements Serializable {

  }
}
{code}

  was:
I hit this with a simple test using DataSerializer to write and read a java Serializable object.

The problem I'm seeing is that there is a difference in the serialized form of an object depending on whether DataSerializer is passed an ObjectInputStream or just a DataInputStream.

With ObjectInputStream DataSerializer.writeObject just calls writeObject on the underlying ObjectInputStream. With DataInputStream, DataSerializer constructs a new ObjectInputStream.

The problem is that the constructor for ObjectInputStream actually writes two shorts to the stream. So the serialized form may or may not include those two shorts.

DataSerializer.writeObject expects to read those two shorts, because it constructs a DSObjectInputStream unless the input is already a DSObjectInputStream.

Because of that, just writing and reading an object and result in an EOFException:
{noformat}
java.io.EOFException
	at java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2353)
	at java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:2822)
	at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:804)
	at java.io.ObjectInputStream.<init>(ObjectInputStream.java:301)
	at org.apache.geode.internal.InternalDataSerializer$DSObjectInputStream.<init>(InternalDataSerializer.java:3583)
	at org.apache.geode.internal.InternalDataSerializer.basicReadObject(InternalDataSerializer.java:2988)
	at org.apache.geode.DataSerializer.readObject(DataSerializer.java:3281)
	at DataSerializerJUnitTest.test(DataSerializerJUnitTest.java:20)
{noformat}

Here's a simple test of this issue:
{code}
import org.apache.geode.DataSerializer;
import org.junit.Test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class DataSerializerJUnitTest {

  @Test
  public void test() throws IOException, ClassNotFoundException {
    final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    ObjectOutputStream out = new ObjectOutputStream(byteArrayOutputStream);
    DataSerializer.writeObject(new MyObject(), out);
    out.close();
    ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
    final Object object = DataSerializer.readObject(in);
  }

  private static class MyObject implements Serializable {

  }
}
{code}


> Serialized data generated by DataSerializer.writeObject depends on the type of OutputStream
> -------------------------------------------------------------------------------------------
>
>                 Key: GEODE-2130
>                 URL: https://issues.apache.org/jira/browse/GEODE-2130
>             Project: Geode
>          Issue Type: Bug
>          Components: serialization
>            Reporter: Dan Smith
>
> I hit this with a simple test using DataSerializer to write and read a java Serializable object.
> The problem I'm seeing is that there is a difference in the serialized form of an object depending on whether DataSerializer is passed an ObjectInputStream or just a DataInputStream.
> With ObjectInputStream DataSerializer.writeObject just calls writeObject on the underlying ObjectInputStream. With DataInputStream, DataSerializer constructs a new ObjectInputStream.
> The problem is that the constructor for ObjectOutputStream actually writes two shorts to the stream. So the serialized form may or may not include those two shorts.
> DataSerializer.readObject expects to read those two shorts, because it constructs a DSObjectInputStream unless the input is already a DSObjectInputStream.
> Because of that, just writing and reading an object and result in an EOFException:
> {noformat}
> java.io.EOFException
> 	at java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2353)
> 	at java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:2822)
> 	at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:804)
> 	at java.io.ObjectInputStream.<init>(ObjectInputStream.java:301)
> 	at org.apache.geode.internal.InternalDataSerializer$DSObjectInputStream.<init>(InternalDataSerializer.java:3583)
> 	at org.apache.geode.internal.InternalDataSerializer.basicReadObject(InternalDataSerializer.java:2988)
> 	at org.apache.geode.DataSerializer.readObject(DataSerializer.java:3281)
> 	at DataSerializerJUnitTest.test(DataSerializerJUnitTest.java:20)
> {noformat}
> Here's a simple test of this issue:
> {code}
> import org.apache.geode.DataSerializer;
> import org.junit.Test;
> import java.io.ByteArrayInputStream;
> import java.io.ByteArrayOutputStream;
> import java.io.IOException;
> import java.io.ObjectInputStream;
> import java.io.ObjectOutputStream;
> import java.io.Serializable;
> public class DataSerializerJUnitTest {
>   @Test
>   public void test() throws IOException, ClassNotFoundException {
>     final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
>     ObjectOutputStream out = new ObjectOutputStream(byteArrayOutputStream);
>     DataSerializer.writeObject(new MyObject(), out);
>     out.close();
>     ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
>     final Object object = DataSerializer.readObject(in);
>   }
>   private static class MyObject implements Serializable {
>   }
> }
> {code}



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)