title: Why this strange behaviour of ObjectOutputStream and ObjectInputStream throwing EOFException?
body: <p>I wrote a custom serializing/de-serializing logic for persisting some of the data as Java default serialization turned out to be both time and memory expensive. For this purpose I wrote <code>readObject(ObjectInput in)</code> and <code>writeObject(ObjectOutput out)</code> methods for the class(es) that needs persisting. However I noticed that if I do not use any <code>out.writeObject(obj)</code> in <code>writeObject(ObjectOutput out)</code> method then it always throws <code>EOFException</code>.</p>
  
  <p>Consider the following example:</p>
  
  <p><strong>Data.java</strong></p>
  
  <pre><code>public class Data implements BaseData {
  
  private String messageUID;
  private String rawData;
  private String data;
  private Long type;
  private Boolean processed = false;
  private String processedMessage;
  private String processedDetaildMessage;
  
  // getter setter
  
  public void readObject(ObjectInput in) throws IOException, ClassNotFoundException {
      messageUID = in.readUTF();
      rawData = in.readUTF();
      data = in.readUTF();
      type = in.readLong();
      processed = in.readBoolean();
      if (processed) {
          processedMessage = in.readUTF();
          processedDetaildMessage = in.readUTF();
      }
  }
  
  public void writeObject(ObjectOutput out) throws IOException {
      out.writeUTF(messageUID);
      out.writeUTF(rawData);
      out.writeUTF(data);
      out.writeLong(type);
      out.writeBoolean(processed);
      if (processed) {
          out.writeUTF(processedMessage);
          String tempDetailsMessage[] = processedDetaildMessage.split(" more");
          out.writeUTF(tempDetailsMessage[tempDetailsMessage.length - 1]);
      }
  }
  </code></pre>
  
  <p>However whenever I use above code the <code>out</code> stream is always missing some information at the end (from <code>processedDetaildMessage</code> field) and I get <code>EOFException</code> while reading it form <code>in</code>, stacktrace below (Data.java line 216 is <code>processedDetaildMessage = in.readUTF()</code>);</p>
  
  <pre><code>java.io.EOFException
      at java.io.ObjectInputStream$BlockDataInputStream.readByte(ObjectInputStream.java:2766)
      at java.io.ObjectInputStream$BlockDataInputStream.readUTFChar(ObjectInputStream.java:3158)
      at java.io.ObjectInputStream$BlockDataInputStream.readUTFBody(ObjectInputStream.java:3055)
      at java.io.ObjectInputStream$BlockDataInputStream.readUTF(ObjectInputStream.java:2864)
      at java.io.ObjectInputStream.readUTF(ObjectInputStream.java:1072)
      at com.smartstream.common.Data.readObject(Data.java:216)
      at com.smartstream.common.PerformanceTest.getObjectFromBytes(PerformanceTest.java:168)
      at com.smartstream.common.PerformanceTest.access$0(PerformanceTest.java:160)
      at com.smartstream.common.PerformanceTest$1.mapRow(PerformanceTest.java:119)
      at com.smartstream.common.PerformanceTest$1.mapRow(PerformanceTest.java:1)
      at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:92)
      at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:60)
      at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:651)
      at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:589)
      at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:639)
      at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:668)
      at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:676)
      at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:731)
      at com.smartstream.common.PerformanceTest.readFromDb(PerformanceTest.java:109)
      at com.smartstream.common.PerformanceTest.main(PerformanceTest.java:66)
  </code></pre>
  
  <p>so I though I would put some extra byte/s of information at the end after writing all required fields and will not read them so that I don't reach end of file while reading. I tried all of these <code>out.writeByte(-1)</code>, <code>out.writeInt(-1)</code>, <code>out.writeLong(2342343l)</code>, <code>out.writeUTF("END_OF_STREAM")</code> but those make no difference. finally I did this <code>out.writeObject(new String("END_OF_STREAM"))</code> and it works fine. Can someone please explain as to why outputstream misses some information if none of the information is written using <code>writeObject()</code> method. Below is how I read and write to/from streams;</p>
  
  <pre><code>private byte[] getObjectAsBytes(Data data) {
      byte[] byteArray = null;
      ByteArrayOutputStream bos = null;
      ObjectOutputStream oos = null;
      try {
          bos = new ByteArrayOutputStream();
          oos = new ObjectOutputStream(bos);
          // Use this for java default serialization
          // oos.writeObject(data);
          data.writeObject(oos);
          byteArray = bos.toByteArray();
      } catch (IOException e) {
          e.printStackTrace();
      } finally {
          if (oos != null) {
              try {
                  oos.flush();
                  oos.close();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
      }
      return byteArray;
  }
  
  private Data getObjectFromBytes(byte[] byteArray) {
      Data data = new Data();
      ByteArrayInputStream bais = null;
      ObjectInputStream ois = null;
      try {
          bais = new ByteArrayInputStream(byteArray);
          ois = new ObjectInputStream(bais);
          // Use this for java default serialization
          // data = (Data) ois.readObject();
          data.readObject(ois);
      } catch (IOException e) {
          e.printStackTrace();
      } catch (ClassNotFoundException e) {
          e.printStackTrace();
      } finally {
          if (ois != null) {
              try {
                  ois.close();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
      }
      return data;
  }
  </code></pre>
  
  <p>If anyone is interested below is what is written in the streams; </p>
  
  <p><strong>persisted data with original code (throws <code>EOFException</code> and missing information)</strong> (don't confuse the stacktrace with original issue this stacktrace is persisted as field <code>processedDetailedMessage</code>)</p>
  
  <pre><code>¬í---z-------3507319347632941385----FEEDER-----1437052314954 ---This is a random string---N---þ%J---!this is message of processed dataÛ
  Caused by: java.sql.SQLException: ORA-01691: unable to extend lob segment TLM_DBO.SYS_LOB0000076335C00008$$ by 8192 in tablespace WIN_SL_TABLE
  at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:439)
  at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:395)
  at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:802)
  at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:436)
  at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:186)
  at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:521)
  at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:205)
  at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1008)
  at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1307)
  at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3449)
  at oracle.jdbc.driver.OraclePre
  </code></pre>
  
  <p><strong>persisted data after writing extra string at the end using <code>writeObject</code> method</strong></p>
  
  <pre><code>¬í---z-------3507319347632941385----FEEDER-----1437052314954 ---This is a random string---N---þ%J---!this is message of processed dataÛ
  Caused by: java.sql.SQLException: ORA-01691: unable to extend lob segment TLM_DBO.SYS_LOB0000076335C00008$$ by 8192 in tablespace WIN_SL_TABLE
  at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:439)
  at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:395)
  at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:802)
  at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:436)
  at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:186)
  at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:521)
  at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:205)
  at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1008)
  at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1307)
  at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3449)
  at oracle.jdbc.driver.OraclePrz-----NeparedStatement.execute(OraclePreparedStatement.java:3550)
  at oracle.jdbc.driver.OraclePreparedStatementWrapper.execute(OraclePreparedStatementWrapper.java:1374)
  at com.ibm.ws.rsadapter.jdbc.WSJdbcPreparedStatement.pmiExecute(WSJdbcPreparedStatement.java:975)
  at com.ibm.ws.rsadapter.jdbc.WSJdbcPreparedStatement.execute(WSJdbcPreparedStatement.java:642)
  at com.smartstream.control.engine.config.dao.jdbc.ProcessExecutionAuditDetailDao$1.doInPreparedStatement(ProcessExecutionAuditDetailDao.java:115)
  at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:586)
  ... 23t 
  END_OF_STREAM
  </code></pre>
  
  <p><em>PS ---- represents unreadable bytes</em></p>