src/share/classes/java/io/ObjectInputStream.java

Print this page

        

@@ -37,11 +37,10 @@
 import java.security.PrivilegedExceptionAction;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.atomic.AtomicBoolean;
 import static java.io.ObjectStreamClass.processQueue;
 import sun.reflect.misc.ReflectUtil;
 
 /**
  * An ObjectInputStream deserializes primitive data and objects previously

@@ -532,11 +531,11 @@
     {
         SerialCallbackContext ctx = curContext;
         if (ctx == null) {
             throw new NotActiveException("not in call to readObject");
         }
-        Object curObj = ctx.getObj();
+        ctx.checkAndSetUsed();
         ObjectStreamClass curDesc = ctx.getDesc();
         bin.setBlockDataMode(false);
         GetFieldImpl getField = new GetFieldImpl(curDesc);
         getField.readFields();
         bin.setBlockDataMode(true);

@@ -1595,11 +1594,11 @@
 
         ObjectStreamClass desc = new ObjectStreamClass();
         int descHandle = handles.assign(unshared ? unsharedMarker : desc);
         passHandle = NULL_HANDLE;
 
-        ObjectStreamClass readDesc = null;
+        ObjectStreamClass readDesc;
         try {
             readDesc = readClassDescriptor();
         } catch (ClassNotFoundException ex) {
             throw (IOException) new InvalidClassException(
                 "failed to read class descriptor").initCause(ex);

@@ -1974,21 +1973,25 @@
         if (cl != null && obj != null && !cl.isInstance(obj)) {
             throw new ClassCastException();
         }
 
         int primDataSize = desc.getPrimDataSize();
+        if (primDataSize > 0) {
         if (primVals == null || primVals.length < primDataSize) {
             primVals = new byte[primDataSize];
         }
         bin.readFully(primVals, 0, primDataSize, false);
         if (obj != null) {
             desc.setPrimFieldValues(obj, primVals);
         }
+        }
 
+        int numObjFields = desc.getNumObjFields();
+        if (numObjFields > 0) {
         int objHandle = passHandle;
         ObjectStreamField[] fields = desc.getFields(false);
-        Object[] objVals = new Object[desc.getNumObjFields()];
+            Object[] objVals = new Object[numObjFields];
         int numPrimFields = fields.length - objVals.length;
         for (int i = 0; i < objVals.length; i++) {
             ObjectStreamField f = fields[numPrimFields + i];
             objVals[i] = readObject0(f.isUnshared());
             if (f.getField() != null) {

@@ -1998,10 +2001,11 @@
         if (obj != null) {
             desc.setObjFieldValues(obj, objVals);
         }
         passHandle = objHandle;
     }
+    }
 
     /**
      * Reads in and returns IOException that caused serialization to abort.
      * All stream state is discarded prior to reading in fatal exception.  Sets
      * passHandle to fatal exception's handle.

@@ -2375,12 +2379,16 @@
 
         /** buffer for reading general/block data */
         private final byte[] buf = new byte[MAX_BLOCK_SIZE];
         /** buffer for reading block data headers */
         private final byte[] hbuf = new byte[MAX_HEADER_SIZE];
-        /** char buffer for fast string reads */
+        /** char buffer for fast string reads - used by {@link #readUTFSpan(long)} */
         private final char[] cbuf = new char[CHAR_BUF_SIZE];
+        /** shared string builder for less object allocations - used by
+         * {@link #readUTFBody(long)}, {@link #readUTFChar(long)} and
+         * {@link #readUTFSpan(long)} */
+        private final StringBuilder sbuf = new StringBuilder(CHAR_BUF_SIZE);
 
         /** block data mode */
         private boolean blkmode = false;
 
         // block data state fields; values meaningful only when blkmode true

@@ -3042,23 +3050,23 @@
          * Reads in the "body" (i.e., the UTF representation minus the 2-byte
          * or 8-byte length header) of a UTF encoding, which occupies the next
          * utflen bytes.
          */
         private String readUTFBody(long utflen) throws IOException {
-            StringBuilder sbuf = new StringBuilder();
             if (!blkmode) {
                 end = pos = 0;
             }
 
+            sbuf.setLength(0);
             while (utflen > 0) {
                 int avail = end - pos;
                 if (avail >= 3 || (long) avail == utflen) {
-                    utflen -= readUTFSpan(sbuf, utflen);
+                    utflen -= readUTFSpan(utflen);
                 } else {
                     if (blkmode) {
                         // near block boundary, read one byte at a time
-                        utflen -= readUTFChar(sbuf, utflen);
+                        utflen -= readUTFChar(utflen);
                     } else {
                         // shift and refill buffer manually
                         if (avail > 0) {
                             System.arraycopy(buf, pos, buf, 0, avail);
                         }

@@ -3074,13 +3082,13 @@
 
         /**
          * Reads span of UTF-encoded characters out of internal buffer
          * (starting at offset pos and ending at or before offset end),
          * consuming no more than utflen bytes.  Appends read characters to
-         * sbuf.  Returns the number of bytes consumed.
+         * {@link #sbuf}.  Returns the number of bytes consumed.
          */
-        private long readUTFSpan(StringBuilder sbuf, long utflen)
+        private long readUTFSpan(long utflen)
             throws IOException
         {
             int cpos = 0;
             int start = pos;
             int avail = Math.min(end - pos, CHAR_BUF_SIZE);

@@ -3148,16 +3156,16 @@
             return pos - start;
         }
 
         /**
          * Reads in single UTF-encoded character one byte at a time, appends
-         * the character to sbuf, and returns the number of bytes consumed.
+         * the character to {@link #sbuf}, and returns the number of bytes consumed.
          * This method is used when reading in UTF strings written in block
          * data mode to handle UTF-encoded characters which (potentially)
          * straddle block-data boundaries.
          */
-        private int readUTFChar(StringBuilder sbuf, long utflen)
+        private int readUTFChar(long utflen)
             throws IOException
         {
             int b1, b2, b3;
             b1 = readByte() & 0xFF;
             switch (b1 >> 4) {