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

Print this page




  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.lang.reflect.Array;
  31 import java.lang.reflect.Modifier;
  32 import java.lang.reflect.Proxy;
  33 import java.security.AccessControlContext;
  34 import java.security.AccessController;
  35 import java.security.PrivilegedAction;
  36 import java.security.PrivilegedActionException;
  37 import java.security.PrivilegedExceptionAction;
  38 import java.util.Arrays;
  39 import java.util.HashMap;
  40 import java.util.concurrent.ConcurrentHashMap;
  41 import java.util.concurrent.ConcurrentMap;
  42 import java.util.concurrent.atomic.AtomicBoolean;
  43 import static java.io.ObjectStreamClass.processQueue;
  44 import sun.reflect.misc.ReflectUtil;
  45 
  46 /**
  47  * An ObjectInputStream deserializes primitive data and objects previously
  48  * written using an ObjectOutputStream.
  49  *
  50  * <p>ObjectOutputStream and ObjectInputStream can provide an application with
  51  * persistent storage for graphs of objects when used with a FileOutputStream
  52  * and FileInputStream respectively.  ObjectInputStream is used to recover
  53  * those objects previously serialized. Other uses include passing objects
  54  * between hosts using a socket stream or for marshaling and unmarshaling
  55  * arguments and parameters in a remote communication system.
  56  *
  57  * <p>ObjectInputStream ensures that the types of all objects in the graph
  58  * created from the stream match the classes present in the Java Virtual
  59  * Machine.  Classes are loaded as required using the standard mechanisms.
  60  *
  61  * <p>Only objects that support the java.io.Serializable or
  62  * java.io.Externalizable interface can be read from streams.


 517     /**
 518      * Reads the persistent fields from the stream and makes them available by
 519      * name.
 520      *
 521      * @return  the <code>GetField</code> object representing the persistent
 522      *          fields of the object being deserialized
 523      * @throws  ClassNotFoundException if the class of a serialized object
 524      *          could not be found.
 525      * @throws  IOException if an I/O error occurs.
 526      * @throws  NotActiveException if the stream is not currently reading
 527      *          objects.
 528      * @since 1.2
 529      */
 530     public ObjectInputStream.GetField readFields()
 531         throws IOException, ClassNotFoundException
 532     {
 533         SerialCallbackContext ctx = curContext;
 534         if (ctx == null) {
 535             throw new NotActiveException("not in call to readObject");
 536         }
 537         Object curObj = ctx.getObj();
 538         ObjectStreamClass curDesc = ctx.getDesc();
 539         bin.setBlockDataMode(false);
 540         GetFieldImpl getField = new GetFieldImpl(curDesc);
 541         getField.readFields();
 542         bin.setBlockDataMode(true);
 543         if (!curDesc.hasWriteObjectData()) {
 544             /*
 545              * Fix for 4360508: since stream does not contain terminating
 546              * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
 547              * knows to simulate end-of-custom-data behavior.
 548              */
 549             defaultDataEnd = true;
 550         }
 551 
 552         return getField;
 553     }
 554 
 555     /**
 556      * Register an object to be validated before the graph is returned.  While
 557      * similar to resolveObject these validations are called after the entire


1580         return desc;
1581     }
1582 
1583     /**
1584      * Reads in and returns class descriptor for a class that is not a dynamic
1585      * proxy class.  Sets passHandle to class descriptor's assigned handle.  If
1586      * class descriptor cannot be resolved to a class in the local VM, a
1587      * ClassNotFoundException is associated with the descriptor's handle.
1588      */
1589     private ObjectStreamClass readNonProxyDesc(boolean unshared)
1590         throws IOException
1591     {
1592         if (bin.readByte() != TC_CLASSDESC) {
1593             throw new InternalError();
1594         }
1595 
1596         ObjectStreamClass desc = new ObjectStreamClass();
1597         int descHandle = handles.assign(unshared ? unsharedMarker : desc);
1598         passHandle = NULL_HANDLE;
1599 
1600         ObjectStreamClass readDesc = null;
1601         try {
1602             readDesc = readClassDescriptor();
1603         } catch (ClassNotFoundException ex) {
1604             throw (IOException) new InvalidClassException(
1605                 "failed to read class descriptor").initCause(ex);
1606         }
1607 
1608         Class<?> cl = null;
1609         ClassNotFoundException resolveEx = null;
1610         bin.setBlockDataMode(true);
1611         final boolean checksRequired = isCustomSubclass();
1612         try {
1613             if ((cl = resolveClass(readDesc)) == null) {
1614                 resolveEx = new ClassNotFoundException("null class");
1615             } else if (checksRequired) {
1616                 ReflectUtil.checkPackageAccess(cl);
1617             }
1618         } catch (ClassNotFoundException ex) {
1619             resolveEx = ex;
1620         }


1959                     readObject0(false);
1960                     break;
1961             }
1962         }
1963     }
1964 
1965     /**
1966      * Reads in values of serializable fields declared by given class
1967      * descriptor.  If obj is non-null, sets field values in obj.  Expects that
1968      * passHandle is set to obj's handle before this method is called.
1969      */
1970     private void defaultReadFields(Object obj, ObjectStreamClass desc)
1971         throws IOException
1972     {
1973         Class<?> cl = desc.forClass();
1974         if (cl != null && obj != null && !cl.isInstance(obj)) {
1975             throw new ClassCastException();
1976         }
1977 
1978         int primDataSize = desc.getPrimDataSize();

1979         if (primVals == null || primVals.length < primDataSize) {
1980             primVals = new byte[primDataSize];
1981         }
1982         bin.readFully(primVals, 0, primDataSize, false);
1983         if (obj != null) {
1984             desc.setPrimFieldValues(obj, primVals);
1985         }

1986 


1987         int objHandle = passHandle;
1988         ObjectStreamField[] fields = desc.getFields(false);
1989         Object[] objVals = new Object[desc.getNumObjFields()];
1990         int numPrimFields = fields.length - objVals.length;
1991         for (int i = 0; i < objVals.length; i++) {
1992             ObjectStreamField f = fields[numPrimFields + i];
1993             objVals[i] = readObject0(f.isUnshared());
1994             if (f.getField() != null) {
1995                 handles.markDependency(objHandle, passHandle);
1996             }
1997         }
1998         if (obj != null) {
1999             desc.setObjFieldValues(obj, objVals);
2000         }
2001         passHandle = objHandle;
2002     }

2003 
2004     /**
2005      * Reads in and returns IOException that caused serialization to abort.
2006      * All stream state is discarded prior to reading in fatal exception.  Sets
2007      * passHandle to fatal exception's handle.
2008      */
2009     private IOException readFatalException() throws IOException {
2010         if (bin.readByte() != TC_EXCEPTION) {
2011             throw new InternalError();
2012         }
2013         clear();
2014         return (IOException) readObject0(false);
2015     }
2016 
2017     /**
2018      * If recursion depth is 0, clears internal data structures; otherwise,
2019      * throws a StreamCorruptedException.  This method is called when a
2020      * TC_RESET typecode is encountered.
2021      */
2022     private void handleReset() throws StreamCorruptedException {


2360      * for details).  Buffering depends on block data mode: when in default
2361      * mode, no data is buffered in advance; when in block data mode, all data
2362      * for the current data block is read in at once (and buffered).
2363      */
2364     private class BlockDataInputStream
2365         extends InputStream implements DataInput
2366     {
2367         /** maximum data block length */
2368         private static final int MAX_BLOCK_SIZE = 1024;
2369         /** maximum data block header length */
2370         private static final int MAX_HEADER_SIZE = 5;
2371         /** (tunable) length of char buffer (for reading strings) */
2372         private static final int CHAR_BUF_SIZE = 256;
2373         /** readBlockHeader() return value indicating header read may block */
2374         private static final int HEADER_BLOCKED = -2;
2375 
2376         /** buffer for reading general/block data */
2377         private final byte[] buf = new byte[MAX_BLOCK_SIZE];
2378         /** buffer for reading block data headers */
2379         private final byte[] hbuf = new byte[MAX_HEADER_SIZE];
2380         /** char buffer for fast string reads */
2381         private final char[] cbuf = new char[CHAR_BUF_SIZE];




2382 
2383         /** block data mode */
2384         private boolean blkmode = false;
2385 
2386         // block data state fields; values meaningful only when blkmode true
2387         /** current offset into buf */
2388         private int pos = 0;
2389         /** end offset of valid data in buf, or -1 if no more block data */
2390         private int end = -1;
2391         /** number of bytes in current block yet to be read from stream */
2392         private int unread = 0;
2393 
2394         /** underlying stream (wrapped in peekable filter stream) */
2395         private final PeekInputStream in;
2396         /** loopback stream (for data reads that span data blocks) */
2397         private final DataInputStream din;
2398 
2399         /**
2400          * Creates new BlockDataInputStream on top of given underlying stream.
2401          * Block data mode is turned off by default.


3027                 off += span;
3028                 pos += span << 3;
3029             }
3030         }
3031 
3032         /**
3033          * Reads in string written in "long" UTF format.  "Long" UTF format is
3034          * identical to standard UTF, except that it uses an 8 byte header
3035          * (instead of the standard 2 bytes) to convey the UTF encoding length.
3036          */
3037         String readLongUTF() throws IOException {
3038             return readUTFBody(readLong());
3039         }
3040 
3041         /**
3042          * Reads in the "body" (i.e., the UTF representation minus the 2-byte
3043          * or 8-byte length header) of a UTF encoding, which occupies the next
3044          * utflen bytes.
3045          */
3046         private String readUTFBody(long utflen) throws IOException {
3047             StringBuilder sbuf = new StringBuilder();
3048             if (!blkmode) {
3049                 end = pos = 0;
3050             }
3051 

3052             while (utflen > 0) {
3053                 int avail = end - pos;
3054                 if (avail >= 3 || (long) avail == utflen) {
3055                     utflen -= readUTFSpan(sbuf, utflen);
3056                 } else {
3057                     if (blkmode) {
3058                         // near block boundary, read one byte at a time
3059                         utflen -= readUTFChar(sbuf, utflen);
3060                     } else {
3061                         // shift and refill buffer manually
3062                         if (avail > 0) {
3063                             System.arraycopy(buf, pos, buf, 0, avail);
3064                         }
3065                         pos = 0;
3066                         end = (int) Math.min(MAX_BLOCK_SIZE, utflen);
3067                         in.readFully(buf, avail, end - avail);
3068                     }
3069                 }
3070             }
3071 
3072             return sbuf.toString();
3073         }
3074 
3075         /**
3076          * Reads span of UTF-encoded characters out of internal buffer
3077          * (starting at offset pos and ending at or before offset end),
3078          * consuming no more than utflen bytes.  Appends read characters to
3079          * sbuf.  Returns the number of bytes consumed.
3080          */
3081         private long readUTFSpan(StringBuilder sbuf, long utflen)
3082             throws IOException
3083         {
3084             int cpos = 0;
3085             int start = pos;
3086             int avail = Math.min(end - pos, CHAR_BUF_SIZE);
3087             // stop short of last char unless all of utf bytes in buffer
3088             int stop = pos + ((utflen > avail) ? avail - 2 : (int) utflen);
3089             boolean outOfBounds = false;
3090 
3091             try {
3092                 while (pos < stop) {
3093                     int b1, b2, b3;
3094                     b1 = buf[pos++] & 0xFF;
3095                     switch (b1 >> 4) {
3096                         case 0:
3097                         case 1:
3098                         case 2:
3099                         case 3:
3100                         case 4:
3101                         case 5:


3133             } catch (ArrayIndexOutOfBoundsException ex) {
3134                 outOfBounds = true;
3135             } finally {
3136                 if (outOfBounds || (pos - start) > utflen) {
3137                     /*
3138                      * Fix for 4450867: if a malformed utf char causes the
3139                      * conversion loop to scan past the expected end of the utf
3140                      * string, only consume the expected number of utf bytes.
3141                      */
3142                     pos = start + (int) utflen;
3143                     throw new UTFDataFormatException();
3144                 }
3145             }
3146 
3147             sbuf.append(cbuf, 0, cpos);
3148             return pos - start;
3149         }
3150 
3151         /**
3152          * Reads in single UTF-encoded character one byte at a time, appends
3153          * the character to sbuf, and returns the number of bytes consumed.
3154          * This method is used when reading in UTF strings written in block
3155          * data mode to handle UTF-encoded characters which (potentially)
3156          * straddle block-data boundaries.
3157          */
3158         private int readUTFChar(StringBuilder sbuf, long utflen)
3159             throws IOException
3160         {
3161             int b1, b2, b3;
3162             b1 = readByte() & 0xFF;
3163             switch (b1 >> 4) {
3164                 case 0:
3165                 case 1:
3166                 case 2:
3167                 case 3:
3168                 case 4:
3169                 case 5:
3170                 case 6:
3171                 case 7:     // 1 byte format: 0xxxxxxx
3172                     sbuf.append((char) b1);
3173                     return 1;
3174 
3175                 case 12:
3176                 case 13:    // 2 byte format: 110xxxxx 10xxxxxx
3177                     if (utflen < 2) {
3178                         throw new UTFDataFormatException();




  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.lang.reflect.Array;
  31 import java.lang.reflect.Modifier;
  32 import java.lang.reflect.Proxy;
  33 import java.security.AccessControlContext;
  34 import java.security.AccessController;
  35 import java.security.PrivilegedAction;
  36 import java.security.PrivilegedActionException;
  37 import java.security.PrivilegedExceptionAction;
  38 import java.util.Arrays;
  39 import java.util.HashMap;
  40 import java.util.concurrent.ConcurrentHashMap;
  41 import java.util.concurrent.ConcurrentMap;

  42 import static java.io.ObjectStreamClass.processQueue;
  43 import sun.reflect.misc.ReflectUtil;
  44 
  45 /**
  46  * An ObjectInputStream deserializes primitive data and objects previously
  47  * written using an ObjectOutputStream.
  48  *
  49  * <p>ObjectOutputStream and ObjectInputStream can provide an application with
  50  * persistent storage for graphs of objects when used with a FileOutputStream
  51  * and FileInputStream respectively.  ObjectInputStream is used to recover
  52  * those objects previously serialized. Other uses include passing objects
  53  * between hosts using a socket stream or for marshaling and unmarshaling
  54  * arguments and parameters in a remote communication system.
  55  *
  56  * <p>ObjectInputStream ensures that the types of all objects in the graph
  57  * created from the stream match the classes present in the Java Virtual
  58  * Machine.  Classes are loaded as required using the standard mechanisms.
  59  *
  60  * <p>Only objects that support the java.io.Serializable or
  61  * java.io.Externalizable interface can be read from streams.


 516     /**
 517      * Reads the persistent fields from the stream and makes them available by
 518      * name.
 519      *
 520      * @return  the <code>GetField</code> object representing the persistent
 521      *          fields of the object being deserialized
 522      * @throws  ClassNotFoundException if the class of a serialized object
 523      *          could not be found.
 524      * @throws  IOException if an I/O error occurs.
 525      * @throws  NotActiveException if the stream is not currently reading
 526      *          objects.
 527      * @since 1.2
 528      */
 529     public ObjectInputStream.GetField readFields()
 530         throws IOException, ClassNotFoundException
 531     {
 532         SerialCallbackContext ctx = curContext;
 533         if (ctx == null) {
 534             throw new NotActiveException("not in call to readObject");
 535         }
 536         ctx.checkAndSetUsed();
 537         ObjectStreamClass curDesc = ctx.getDesc();
 538         bin.setBlockDataMode(false);
 539         GetFieldImpl getField = new GetFieldImpl(curDesc);
 540         getField.readFields();
 541         bin.setBlockDataMode(true);
 542         if (!curDesc.hasWriteObjectData()) {
 543             /*
 544              * Fix for 4360508: since stream does not contain terminating
 545              * TC_ENDBLOCKDATA tag, set flag so that reading code elsewhere
 546              * knows to simulate end-of-custom-data behavior.
 547              */
 548             defaultDataEnd = true;
 549         }
 550 
 551         return getField;
 552     }
 553 
 554     /**
 555      * Register an object to be validated before the graph is returned.  While
 556      * similar to resolveObject these validations are called after the entire


1579         return desc;
1580     }
1581 
1582     /**
1583      * Reads in and returns class descriptor for a class that is not a dynamic
1584      * proxy class.  Sets passHandle to class descriptor's assigned handle.  If
1585      * class descriptor cannot be resolved to a class in the local VM, a
1586      * ClassNotFoundException is associated with the descriptor's handle.
1587      */
1588     private ObjectStreamClass readNonProxyDesc(boolean unshared)
1589         throws IOException
1590     {
1591         if (bin.readByte() != TC_CLASSDESC) {
1592             throw new InternalError();
1593         }
1594 
1595         ObjectStreamClass desc = new ObjectStreamClass();
1596         int descHandle = handles.assign(unshared ? unsharedMarker : desc);
1597         passHandle = NULL_HANDLE;
1598 
1599         ObjectStreamClass readDesc;
1600         try {
1601             readDesc = readClassDescriptor();
1602         } catch (ClassNotFoundException ex) {
1603             throw (IOException) new InvalidClassException(
1604                 "failed to read class descriptor").initCause(ex);
1605         }
1606 
1607         Class<?> cl = null;
1608         ClassNotFoundException resolveEx = null;
1609         bin.setBlockDataMode(true);
1610         final boolean checksRequired = isCustomSubclass();
1611         try {
1612             if ((cl = resolveClass(readDesc)) == null) {
1613                 resolveEx = new ClassNotFoundException("null class");
1614             } else if (checksRequired) {
1615                 ReflectUtil.checkPackageAccess(cl);
1616             }
1617         } catch (ClassNotFoundException ex) {
1618             resolveEx = ex;
1619         }


1958                     readObject0(false);
1959                     break;
1960             }
1961         }
1962     }
1963 
1964     /**
1965      * Reads in values of serializable fields declared by given class
1966      * descriptor.  If obj is non-null, sets field values in obj.  Expects that
1967      * passHandle is set to obj's handle before this method is called.
1968      */
1969     private void defaultReadFields(Object obj, ObjectStreamClass desc)
1970         throws IOException
1971     {
1972         Class<?> cl = desc.forClass();
1973         if (cl != null && obj != null && !cl.isInstance(obj)) {
1974             throw new ClassCastException();
1975         }
1976 
1977         int primDataSize = desc.getPrimDataSize();
1978         if (primDataSize > 0) {
1979             if (primVals == null || primVals.length < primDataSize) {
1980             primVals = new byte[primDataSize];
1981             }
1982             bin.readFully(primVals, 0, primDataSize, false);
1983             if (obj != null) {
1984                 desc.setPrimFieldValues(obj, primVals);
1985             }
1986         }
1987 
1988         int numObjFields = desc.getNumObjFields();
1989         if (numObjFields > 0) {
1990             int objHandle = passHandle;
1991             ObjectStreamField[] fields = desc.getFields(false);
1992             Object[] objVals = new Object[numObjFields];
1993             int numPrimFields = fields.length - objVals.length;
1994             for (int i = 0; i < objVals.length; i++) {
1995                 ObjectStreamField f = fields[numPrimFields + i];
1996                 objVals[i] = readObject0(f.isUnshared());
1997                 if (f.getField() != null) {
1998                     handles.markDependency(objHandle, passHandle);
1999                 }
2000             }
2001             if (obj != null) {
2002                 desc.setObjFieldValues(obj, objVals);
2003             }
2004             passHandle = objHandle;
2005         }
2006     }
2007 
2008     /**
2009      * Reads in and returns IOException that caused serialization to abort.
2010      * All stream state is discarded prior to reading in fatal exception.  Sets
2011      * passHandle to fatal exception's handle.
2012      */
2013     private IOException readFatalException() throws IOException {
2014         if (bin.readByte() != TC_EXCEPTION) {
2015             throw new InternalError();
2016         }
2017         clear();
2018         return (IOException) readObject0(false);
2019     }
2020 
2021     /**
2022      * If recursion depth is 0, clears internal data structures; otherwise,
2023      * throws a StreamCorruptedException.  This method is called when a
2024      * TC_RESET typecode is encountered.
2025      */
2026     private void handleReset() throws StreamCorruptedException {


2364      * for details).  Buffering depends on block data mode: when in default
2365      * mode, no data is buffered in advance; when in block data mode, all data
2366      * for the current data block is read in at once (and buffered).
2367      */
2368     private class BlockDataInputStream
2369         extends InputStream implements DataInput
2370     {
2371         /** maximum data block length */
2372         private static final int MAX_BLOCK_SIZE = 1024;
2373         /** maximum data block header length */
2374         private static final int MAX_HEADER_SIZE = 5;
2375         /** (tunable) length of char buffer (for reading strings) */
2376         private static final int CHAR_BUF_SIZE = 256;
2377         /** readBlockHeader() return value indicating header read may block */
2378         private static final int HEADER_BLOCKED = -2;
2379 
2380         /** buffer for reading general/block data */
2381         private final byte[] buf = new byte[MAX_BLOCK_SIZE];
2382         /** buffer for reading block data headers */
2383         private final byte[] hbuf = new byte[MAX_HEADER_SIZE];
2384         /** char buffer for fast string reads - used by {@link #readUTFSpan(long)} */
2385         private final char[] cbuf = new char[CHAR_BUF_SIZE];
2386         /** shared string builder for less object allocations - used by
2387          * {@link #readUTFBody(long)}, {@link #readUTFChar(long)} and
2388          * {@link #readUTFSpan(long)} */
2389         private final StringBuilder sbuf = new StringBuilder(CHAR_BUF_SIZE);
2390 
2391         /** block data mode */
2392         private boolean blkmode = false;
2393 
2394         // block data state fields; values meaningful only when blkmode true
2395         /** current offset into buf */
2396         private int pos = 0;
2397         /** end offset of valid data in buf, or -1 if no more block data */
2398         private int end = -1;
2399         /** number of bytes in current block yet to be read from stream */
2400         private int unread = 0;
2401 
2402         /** underlying stream (wrapped in peekable filter stream) */
2403         private final PeekInputStream in;
2404         /** loopback stream (for data reads that span data blocks) */
2405         private final DataInputStream din;
2406 
2407         /**
2408          * Creates new BlockDataInputStream on top of given underlying stream.
2409          * Block data mode is turned off by default.


3035                 off += span;
3036                 pos += span << 3;
3037             }
3038         }
3039 
3040         /**
3041          * Reads in string written in "long" UTF format.  "Long" UTF format is
3042          * identical to standard UTF, except that it uses an 8 byte header
3043          * (instead of the standard 2 bytes) to convey the UTF encoding length.
3044          */
3045         String readLongUTF() throws IOException {
3046             return readUTFBody(readLong());
3047         }
3048 
3049         /**
3050          * Reads in the "body" (i.e., the UTF representation minus the 2-byte
3051          * or 8-byte length header) of a UTF encoding, which occupies the next
3052          * utflen bytes.
3053          */
3054         private String readUTFBody(long utflen) throws IOException {

3055             if (!blkmode) {
3056                 end = pos = 0;
3057             }
3058 
3059             sbuf.setLength(0);
3060             while (utflen > 0) {
3061                 int avail = end - pos;
3062                 if (avail >= 3 || (long) avail == utflen) {
3063                     utflen -= readUTFSpan(utflen);
3064                 } else {
3065                     if (blkmode) {
3066                         // near block boundary, read one byte at a time
3067                         utflen -= readUTFChar(utflen);
3068                     } else {
3069                         // shift and refill buffer manually
3070                         if (avail > 0) {
3071                             System.arraycopy(buf, pos, buf, 0, avail);
3072                         }
3073                         pos = 0;
3074                         end = (int) Math.min(MAX_BLOCK_SIZE, utflen);
3075                         in.readFully(buf, avail, end - avail);
3076                     }
3077                 }
3078             }
3079 
3080             return sbuf.toString();
3081         }
3082 
3083         /**
3084          * Reads span of UTF-encoded characters out of internal buffer
3085          * (starting at offset pos and ending at or before offset end),
3086          * consuming no more than utflen bytes.  Appends read characters to
3087          * {@link #sbuf}.  Returns the number of bytes consumed.
3088          */
3089         private long readUTFSpan(long utflen)
3090             throws IOException
3091         {
3092             int cpos = 0;
3093             int start = pos;
3094             int avail = Math.min(end - pos, CHAR_BUF_SIZE);
3095             // stop short of last char unless all of utf bytes in buffer
3096             int stop = pos + ((utflen > avail) ? avail - 2 : (int) utflen);
3097             boolean outOfBounds = false;
3098 
3099             try {
3100                 while (pos < stop) {
3101                     int b1, b2, b3;
3102                     b1 = buf[pos++] & 0xFF;
3103                     switch (b1 >> 4) {
3104                         case 0:
3105                         case 1:
3106                         case 2:
3107                         case 3:
3108                         case 4:
3109                         case 5:


3141             } catch (ArrayIndexOutOfBoundsException ex) {
3142                 outOfBounds = true;
3143             } finally {
3144                 if (outOfBounds || (pos - start) > utflen) {
3145                     /*
3146                      * Fix for 4450867: if a malformed utf char causes the
3147                      * conversion loop to scan past the expected end of the utf
3148                      * string, only consume the expected number of utf bytes.
3149                      */
3150                     pos = start + (int) utflen;
3151                     throw new UTFDataFormatException();
3152                 }
3153             }
3154 
3155             sbuf.append(cbuf, 0, cpos);
3156             return pos - start;
3157         }
3158 
3159         /**
3160          * Reads in single UTF-encoded character one byte at a time, appends
3161          * the character to {@link #sbuf}, and returns the number of bytes consumed.
3162          * This method is used when reading in UTF strings written in block
3163          * data mode to handle UTF-encoded characters which (potentially)
3164          * straddle block-data boundaries.
3165          */
3166         private int readUTFChar(long utflen)
3167             throws IOException
3168         {
3169             int b1, b2, b3;
3170             b1 = readByte() & 0xFF;
3171             switch (b1 >> 4) {
3172                 case 0:
3173                 case 1:
3174                 case 2:
3175                 case 3:
3176                 case 4:
3177                 case 5:
3178                 case 6:
3179                 case 7:     // 1 byte format: 0xxxxxxx
3180                     sbuf.append((char) b1);
3181                     return 1;
3182 
3183                 case 12:
3184                 case 13:    // 2 byte format: 110xxxxx 10xxxxxx
3185                     if (utflen < 2) {
3186                         throw new UTFDataFormatException();