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 }
|