src/share/classes/java/io/ObjectOutputStream.java

Print this page




  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.io;
  27 
  28 import java.io.ObjectStreamClass.WeakClassKey;
  29 import java.lang.ref.ReferenceQueue;
  30 import java.security.AccessController;
  31 import java.security.PrivilegedAction;
  32 import java.util.ArrayList;
  33 import java.util.Arrays;
  34 import java.util.List;
  35 import java.util.concurrent.ConcurrentHashMap;
  36 import java.util.concurrent.ConcurrentMap;
  37 import static java.io.ObjectStreamClass.processQueue;
  38 import java.io.SerialCallbackContext;
  39 import sun.reflect.misc.ReflectUtil;
  40 
  41 /**
  42  * An ObjectOutputStream writes primitive data types and graphs of Java objects
  43  * to an OutputStream.  The objects can be read (reconstituted) using an
  44  * ObjectInputStream.  Persistent storage of objects can be accomplished by
  45  * using a file for the stream.  If the stream is a network socket stream, the
  46  * objects can be reconstituted on another host or in another process.
  47  *
  48  * <p>Only objects that support the java.io.Serializable interface can be
  49  * written to streams.  The class of each serializable object is encoded
  50  * including the class name and signature of the class, the values of the
  51  * object's fields and arrays, and the closure of any other objects referenced
  52  * from the initial objects.
  53  *
  54  * <p>The method writeObject is used to write an object to the stream.  Any
  55  * object, including Strings and arrays, is written with writeObject. Multiple
  56  * objects or primitives can be written to the stream.  The objects must be
  57  * read back from the corresponding ObjectInputstream with the same types and
  58  * in the same order as they were written.


 441         defaultWriteFields(curObj, curDesc);
 442         bout.setBlockDataMode(true);
 443     }
 444 
 445     /**
 446      * Retrieve the object used to buffer persistent fields to be written to
 447      * the stream.  The fields will be written to the stream when writeFields
 448      * method is called.
 449      *
 450      * @return  an instance of the class Putfield that holds the serializable
 451      *          fields
 452      * @throws  IOException if I/O errors occur
 453      * @since 1.2
 454      */
 455     public ObjectOutputStream.PutField putFields() throws IOException {
 456         if (curPut == null) {
 457             SerialCallbackContext ctx = curContext;
 458             if (ctx == null) {
 459                 throw new NotActiveException("not in call to writeObject");
 460             }
 461             Object curObj = ctx.getObj();
 462             ObjectStreamClass curDesc = ctx.getDesc();
 463             curPut = new PutFieldImpl(curDesc);
 464         }
 465         return curPut;
 466     }
 467 
 468     /**
 469      * Write the buffered fields to the stream.
 470      *
 471      * @throws  IOException if I/O errors occur while writing to the underlying
 472      *          stream
 473      * @throws  NotActiveException Called when a classes writeObject method was
 474      *          not called to write the state of the object.
 475      * @since 1.2
 476      */
 477     public void writeFields() throws IOException {
 478         if (curPut == null) {
 479             throw new NotActiveException("no current PutField object");
 480         }
 481         bout.setBlockDataMode(false);


1510             }
1511         }
1512     }
1513 
1514     /**
1515      * Fetches and writes values of serializable fields of given object to
1516      * stream.  The given class descriptor specifies which field values to
1517      * write, and in which order they should be written.
1518      */
1519     private void defaultWriteFields(Object obj, ObjectStreamClass desc)
1520         throws IOException
1521     {
1522         Class<?> cl = desc.forClass();
1523         if (cl != null && obj != null && !cl.isInstance(obj)) {
1524             throw new ClassCastException();
1525         }
1526 
1527         desc.checkDefaultSerialize();
1528 
1529         int primDataSize = desc.getPrimDataSize();

1530         if (primVals == null || primVals.length < primDataSize) {
1531             primVals = new byte[primDataSize];
1532         }
1533         desc.getPrimFieldValues(obj, primVals);
1534         bout.write(primVals, 0, primDataSize, false);

1535 


1536         ObjectStreamField[] fields = desc.getFields(false);
1537         Object[] objVals = new Object[desc.getNumObjFields()];
1538         int numPrimFields = fields.length - objVals.length;
1539         desc.getObjFieldValues(obj, objVals);
1540         for (int i = 0; i < objVals.length; i++) {
1541             if (extendedDebugInfo) {
1542                 debugInfoStack.push(
1543                     "field (class \"" + desc.getName() + "\", name: \"" +
1544                     fields[numPrimFields + i].getName() + "\", type: \"" +
1545                     fields[numPrimFields + i].getType() + "\")");
1546             }
1547             try {
1548                 writeObject0(objVals[i],
1549                              fields[numPrimFields + i].isUnshared());
1550             } finally {
1551                 if (extendedDebugInfo) {
1552                     debugInfoStack.pop();
1553                 }
1554             }
1555         }
1556     }

1557 
1558     /**
1559      * Attempts to write to stream fatal IOException that has caused
1560      * serialization to abort.
1561      */
1562     private void writeFatalException(IOException ex) throws IOException {
1563         /*
1564          * Note: the serialization specification states that if a second
1565          * IOException occurs while attempting to serialize the original fatal
1566          * exception to the stream, then a StreamCorruptedException should be
1567          * thrown (section 2.1).  However, due to a bug in previous
1568          * implementations of serialization, StreamCorruptedExceptions were
1569          * rarely (if ever) actually thrown--the "root" exceptions from
1570          * underlying streams were thrown instead.  This historical behavior is
1571          * followed here for consistency.
1572          */
1573         clear();
1574         boolean oldMode = bout.setBlockDataMode(false);
1575         try {
1576             bout.writeByte(TC_EXCEPTION);


2447          * Removes the object at the top of enclosed list.
2448          */
2449         void pop() {
2450             stack.remove(stack.size()-1);
2451         }
2452 
2453         /**
2454          * Pushes a String onto the top of enclosed list.
2455          */
2456         void push(String entry) {
2457             stack.add("\t- " + entry);
2458         }
2459 
2460         /**
2461          * Returns a string representation of this object
2462          */
2463         public String toString() {
2464             StringBuilder buffer = new StringBuilder();
2465             if (!stack.isEmpty()) {
2466                 for(int i = stack.size(); i > 0; i-- ) {
2467                     buffer.append(stack.get(i-1) + ((i != 1) ? "\n" : ""));


2468                 }
2469             }
2470             return buffer.toString();
2471         }
2472     }
2473 
2474 }


  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.io;
  27 
  28 import java.io.ObjectStreamClass.WeakClassKey;
  29 import java.lang.ref.ReferenceQueue;
  30 import java.security.AccessController;
  31 import java.security.PrivilegedAction;
  32 import java.util.ArrayList;
  33 import java.util.Arrays;
  34 import java.util.List;
  35 import java.util.concurrent.ConcurrentHashMap;
  36 import java.util.concurrent.ConcurrentMap;
  37 import static java.io.ObjectStreamClass.processQueue;

  38 import sun.reflect.misc.ReflectUtil;
  39 
  40 /**
  41  * An ObjectOutputStream writes primitive data types and graphs of Java objects
  42  * to an OutputStream.  The objects can be read (reconstituted) using an
  43  * ObjectInputStream.  Persistent storage of objects can be accomplished by
  44  * using a file for the stream.  If the stream is a network socket stream, the
  45  * objects can be reconstituted on another host or in another process.
  46  *
  47  * <p>Only objects that support the java.io.Serializable interface can be
  48  * written to streams.  The class of each serializable object is encoded
  49  * including the class name and signature of the class, the values of the
  50  * object's fields and arrays, and the closure of any other objects referenced
  51  * from the initial objects.
  52  *
  53  * <p>The method writeObject is used to write an object to the stream.  Any
  54  * object, including Strings and arrays, is written with writeObject. Multiple
  55  * objects or primitives can be written to the stream.  The objects must be
  56  * read back from the corresponding ObjectInputstream with the same types and
  57  * in the same order as they were written.


 440         defaultWriteFields(curObj, curDesc);
 441         bout.setBlockDataMode(true);
 442     }
 443 
 444     /**
 445      * Retrieve the object used to buffer persistent fields to be written to
 446      * the stream.  The fields will be written to the stream when writeFields
 447      * method is called.
 448      *
 449      * @return  an instance of the class Putfield that holds the serializable
 450      *          fields
 451      * @throws  IOException if I/O errors occur
 452      * @since 1.2
 453      */
 454     public ObjectOutputStream.PutField putFields() throws IOException {
 455         if (curPut == null) {
 456             SerialCallbackContext ctx = curContext;
 457             if (ctx == null) {
 458                 throw new NotActiveException("not in call to writeObject");
 459             }
 460             ctx.checkAndSetUsed();
 461             ObjectStreamClass curDesc = ctx.getDesc();
 462             curPut = new PutFieldImpl(curDesc);
 463         }
 464         return curPut;
 465     }
 466 
 467     /**
 468      * Write the buffered fields to the stream.
 469      *
 470      * @throws  IOException if I/O errors occur while writing to the underlying
 471      *          stream
 472      * @throws  NotActiveException Called when a classes writeObject method was
 473      *          not called to write the state of the object.
 474      * @since 1.2
 475      */
 476     public void writeFields() throws IOException {
 477         if (curPut == null) {
 478             throw new NotActiveException("no current PutField object");
 479         }
 480         bout.setBlockDataMode(false);


1509             }
1510         }
1511     }
1512 
1513     /**
1514      * Fetches and writes values of serializable fields of given object to
1515      * stream.  The given class descriptor specifies which field values to
1516      * write, and in which order they should be written.
1517      */
1518     private void defaultWriteFields(Object obj, ObjectStreamClass desc)
1519         throws IOException
1520     {
1521         Class<?> cl = desc.forClass();
1522         if (cl != null && obj != null && !cl.isInstance(obj)) {
1523             throw new ClassCastException();
1524         }
1525 
1526         desc.checkDefaultSerialize();
1527 
1528         int primDataSize = desc.getPrimDataSize();
1529         if (primDataSize > 0) {
1530             if (primVals == null || primVals.length < primDataSize) {
1531                 primVals = new byte[primDataSize];
1532             }
1533             desc.getPrimFieldValues(obj, primVals);
1534             bout.write(primVals, 0, primDataSize, false);
1535         }
1536 
1537         int numObjFields = desc.getNumObjFields();
1538         if (numObjFields > 0) {
1539             ObjectStreamField[] fields = desc.getFields(false);
1540             Object[] objVals = new Object[numObjFields];
1541             int numPrimFields = fields.length - objVals.length;
1542             desc.getObjFieldValues(obj, objVals);
1543             for (int i = 0; i < objVals.length; i++) {
1544                 if (extendedDebugInfo) {
1545                     debugInfoStack.push(
1546                         "field (class \"" + desc.getName() + "\", name: \"" +
1547                         fields[numPrimFields + i].getName() + "\", type: \"" +
1548                         fields[numPrimFields + i].getType() + "\")");
1549                 }
1550                 try {
1551                     writeObject0(objVals[i],
1552                                  fields[numPrimFields + i].isUnshared());
1553                 } finally {
1554                     if (extendedDebugInfo) {
1555                         debugInfoStack.pop();
1556                     }
1557                 }
1558             }
1559         }
1560     }
1561 
1562     /**
1563      * Attempts to write to stream fatal IOException that has caused
1564      * serialization to abort.
1565      */
1566     private void writeFatalException(IOException ex) throws IOException {
1567         /*
1568          * Note: the serialization specification states that if a second
1569          * IOException occurs while attempting to serialize the original fatal
1570          * exception to the stream, then a StreamCorruptedException should be
1571          * thrown (section 2.1).  However, due to a bug in previous
1572          * implementations of serialization, StreamCorruptedExceptions were
1573          * rarely (if ever) actually thrown--the "root" exceptions from
1574          * underlying streams were thrown instead.  This historical behavior is
1575          * followed here for consistency.
1576          */
1577         clear();
1578         boolean oldMode = bout.setBlockDataMode(false);
1579         try {
1580             bout.writeByte(TC_EXCEPTION);


2451          * Removes the object at the top of enclosed list.
2452          */
2453         void pop() {
2454             stack.remove(stack.size()-1);
2455         }
2456 
2457         /**
2458          * Pushes a String onto the top of enclosed list.
2459          */
2460         void push(String entry) {
2461             stack.add("\t- " + entry);
2462         }
2463 
2464         /**
2465          * Returns a string representation of this object
2466          */
2467         public String toString() {
2468             StringBuilder buffer = new StringBuilder();
2469             if (!stack.isEmpty()) {
2470                 for(int i = stack.size(); i > 0; i-- ) {
2471                     buffer.append(stack.get(i - 1));
2472                     if (i != 1)
2473                         buffer.append('\n');
2474                 }
2475             }
2476             return buffer.toString();
2477         }
2478     }
2479 
2480 }