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

Print this page




 672      * <code>IllegalArgumentException</code>.
 673      *
 674      * @param interfaces the list of interface names that were
 675      *                deserialized in the proxy class descriptor
 676      * @return  a proxy class for the specified interfaces
 677      * @throws        IOException any exception thrown by the underlying
 678      *                <code>InputStream</code>
 679      * @throws        ClassNotFoundException if the proxy class or any of the
 680      *                named interfaces could not be found
 681      * @see ObjectOutputStream#annotateProxyClass(Class)
 682      * @since 1.3
 683      */
 684     protected Class<?> resolveProxyClass(String[] interfaces)
 685         throws IOException, ClassNotFoundException
 686     {
 687         ClassLoader latestLoader = latestUserDefinedLoader();
 688         ClassLoader nonPublicLoader = null;
 689         boolean hasNonPublicInterface = false;
 690 
 691         // define proxy in class loader of non-public interface(s), if any
 692         Class[] classObjs = new Class[interfaces.length];
 693         for (int i = 0; i < interfaces.length; i++) {
 694             Class cl = Class.forName(interfaces[i], false, latestLoader);
 695             if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {
 696                 if (hasNonPublicInterface) {
 697                     if (nonPublicLoader != cl.getClassLoader()) {
 698                         throw new IllegalAccessError(
 699                             "conflicting non-public interface class loaders");
 700                     }
 701                 } else {
 702                     nonPublicLoader = cl.getClassLoader();
 703                     hasNonPublicInterface = true;
 704                 }
 705             }
 706             classObjs[i] = cl;
 707         }
 708         try {
 709             return Proxy.getProxyClass(
 710                 hasNonPublicInterface ? nonPublicLoader : latestLoader,
 711                 classObjs);
 712         } catch (IllegalArgumentException e) {
 713             throw new ClassNotFoundException(null, e);
 714         }


1212          *
1213          * @param  name the name of the field
1214          * @param  val the default value to use if <code>name</code> does not
1215          *         have a value
1216          * @return the value of the named <code>Object</code> field
1217          * @throws IOException if there are I/O errors while reading from the
1218          *         underlying <code>InputStream</code>
1219          * @throws IllegalArgumentException if type of <code>name</code> is
1220          *         not serializable or if the field type is incorrect
1221          */
1222         public abstract Object get(String name, Object val) throws IOException;
1223     }
1224 
1225     /**
1226      * Verifies that this (possibly subclass) instance can be constructed
1227      * without violating security constraints: the subclass must not override
1228      * security-sensitive non-final methods, or else the
1229      * "enableSubclassImplementation" SerializablePermission is checked.
1230      */
1231     private void verifySubclass() {
1232         Class cl = getClass();
1233         if (cl == ObjectInputStream.class) {
1234             return;
1235         }
1236         SecurityManager sm = System.getSecurityManager();
1237         if (sm == null) {
1238             return;
1239         }
1240         processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);
1241         WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);
1242         Boolean result = Caches.subclassAudits.get(key);
1243         if (result == null) {
1244             result = Boolean.valueOf(auditSubclass(cl));
1245             Caches.subclassAudits.putIfAbsent(key, result);
1246         }
1247         if (result.booleanValue()) {
1248             return;
1249         }
1250         sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
1251     }
1252 


1456             // REMIND: what type of exception to throw here?
1457             throw new InvalidObjectException(
1458                 "cannot read back reference as unshared");
1459         }
1460 
1461         Object obj = handles.lookupObject(passHandle);
1462         if (obj == unsharedMarker) {
1463             // REMIND: what type of exception to throw here?
1464             throw new InvalidObjectException(
1465                 "cannot read back reference to unshared object");
1466         }
1467         return obj;
1468     }
1469 
1470     /**
1471      * Reads in and returns class object.  Sets passHandle to class object's
1472      * assigned handle.  Returns null if class is unresolvable (in which case a
1473      * ClassNotFoundException will be associated with the class' handle in the
1474      * handle table).
1475      */
1476     private Class readClass(boolean unshared) throws IOException {
1477         if (bin.readByte() != TC_CLASS) {
1478             throw new InternalError();
1479         }
1480         ObjectStreamClass desc = readClassDesc(false);
1481         Class cl = desc.forClass();
1482         passHandle = handles.assign(unshared ? unsharedMarker : cl);
1483 
1484         ClassNotFoundException resolveEx = desc.getResolveException();
1485         if (resolveEx != null) {
1486             handles.markException(passHandle, resolveEx);
1487         }
1488 
1489         handles.finish(passHandle);
1490         return cl;
1491     }
1492 
1493     /**
1494      * Reads in and returns (possibly null) class descriptor.  Sets passHandle
1495      * to class descriptor's assigned handle.  If class descriptor cannot be
1496      * resolved to a class in the local VM, a ClassNotFoundException is
1497      * associated with the class descriptor's handle.
1498      */
1499     private ObjectStreamClass readClassDesc(boolean unshared)
1500         throws IOException
1501     {


1525      * descriptor cannot be resolved to a class in the local VM, a
1526      * ClassNotFoundException is associated with the descriptor's handle.
1527      */
1528     private ObjectStreamClass readProxyDesc(boolean unshared)
1529         throws IOException
1530     {
1531         if (bin.readByte() != TC_PROXYCLASSDESC) {
1532             throw new InternalError();
1533         }
1534 
1535         ObjectStreamClass desc = new ObjectStreamClass();
1536         int descHandle = handles.assign(unshared ? unsharedMarker : desc);
1537         passHandle = NULL_HANDLE;
1538 
1539         int numIfaces = bin.readInt();
1540         String[] ifaces = new String[numIfaces];
1541         for (int i = 0; i < numIfaces; i++) {
1542             ifaces[i] = bin.readUTF();
1543         }
1544 
1545         Class cl = null;
1546         ClassNotFoundException resolveEx = null;
1547         bin.setBlockDataMode(true);
1548         try {
1549             if ((cl = resolveProxyClass(ifaces)) == null) {
1550                 resolveEx = new ClassNotFoundException("null class");
1551             }
1552         } catch (ClassNotFoundException ex) {
1553             resolveEx = ex;
1554         }
1555         skipCustomData();
1556 
1557         desc.initProxy(cl, resolveEx, readClassDesc(false));
1558 
1559         handles.finish(descHandle);
1560         passHandle = descHandle;
1561         return desc;
1562     }
1563 
1564     /**
1565      * Reads in and returns class descriptor for a class that is not a dynamic


1569      */
1570     private ObjectStreamClass readNonProxyDesc(boolean unshared)
1571         throws IOException
1572     {
1573         if (bin.readByte() != TC_CLASSDESC) {
1574             throw new InternalError();
1575         }
1576 
1577         ObjectStreamClass desc = new ObjectStreamClass();
1578         int descHandle = handles.assign(unshared ? unsharedMarker : desc);
1579         passHandle = NULL_HANDLE;
1580 
1581         ObjectStreamClass readDesc = null;
1582         try {
1583             readDesc = readClassDescriptor();
1584         } catch (ClassNotFoundException ex) {
1585             throw (IOException) new InvalidClassException(
1586                 "failed to read class descriptor").initCause(ex);
1587         }
1588 
1589         Class cl = null;
1590         ClassNotFoundException resolveEx = null;
1591         bin.setBlockDataMode(true);
1592         try {
1593             if ((cl = resolveClass(readDesc)) == null) {
1594                 resolveEx = new ClassNotFoundException("null class");
1595             }
1596         } catch (ClassNotFoundException ex) {
1597             resolveEx = ex;
1598         }
1599         skipCustomData();
1600 
1601         desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false));
1602 
1603         handles.finish(descHandle);
1604         passHandle = descHandle;
1605         return desc;
1606     }
1607 
1608     /**
1609      * Reads in and returns new string.  Sets passHandle to new string's


1626                     String.format("invalid type code: %02X", tc));
1627         }
1628         passHandle = handles.assign(unshared ? unsharedMarker : str);
1629         handles.finish(passHandle);
1630         return str;
1631     }
1632 
1633     /**
1634      * Reads in and returns array object, or null if array class is
1635      * unresolvable.  Sets passHandle to array's assigned handle.
1636      */
1637     private Object readArray(boolean unshared) throws IOException {
1638         if (bin.readByte() != TC_ARRAY) {
1639             throw new InternalError();
1640         }
1641 
1642         ObjectStreamClass desc = readClassDesc(false);
1643         int len = bin.readInt();
1644 
1645         Object array = null;
1646         Class cl, ccl = null;
1647         if ((cl = desc.forClass()) != null) {
1648             ccl = cl.getComponentType();
1649             array = Array.newInstance(ccl, len);
1650         }
1651 
1652         int arrayHandle = handles.assign(unshared ? unsharedMarker : array);
1653         ClassNotFoundException resolveEx = desc.getResolveException();
1654         if (resolveEx != null) {
1655             handles.markException(arrayHandle, resolveEx);
1656         }
1657 
1658         if (ccl == null) {
1659             for (int i = 0; i < len; i++) {
1660                 readObject0(false);
1661             }
1662         } else if (ccl.isPrimitive()) {
1663             if (ccl == Integer.TYPE) {
1664                 bin.readInts((int[]) array, 0, len);
1665             } else if (ccl == Byte.TYPE) {
1666                 bin.readFully((byte[]) array, 0, len, true);


1679             } else {
1680                 throw new InternalError();
1681             }
1682         } else {
1683             Object[] oa = (Object[]) array;
1684             for (int i = 0; i < len; i++) {
1685                 oa[i] = readObject0(false);
1686                 handles.markDependency(arrayHandle, passHandle);
1687             }
1688         }
1689 
1690         handles.finish(arrayHandle);
1691         passHandle = arrayHandle;
1692         return array;
1693     }
1694 
1695     /**
1696      * Reads in and returns enum constant, or null if enum type is
1697      * unresolvable.  Sets passHandle to enum constant's assigned handle.
1698      */
1699     private Enum readEnum(boolean unshared) throws IOException {
1700         if (bin.readByte() != TC_ENUM) {
1701             throw new InternalError();
1702         }
1703 
1704         ObjectStreamClass desc = readClassDesc(false);
1705         if (!desc.isEnum()) {
1706             throw new InvalidClassException("non-enum class: " + desc);
1707         }
1708 
1709         int enumHandle = handles.assign(unshared ? unsharedMarker : null);
1710         ClassNotFoundException resolveEx = desc.getResolveException();
1711         if (resolveEx != null) {
1712             handles.markException(enumHandle, resolveEx);
1713         }
1714 
1715         String name = readString(false);
1716         Enum en = null;
1717         Class cl = desc.forClass();
1718         if (cl != null) {
1719             try {
1720                 en = Enum.valueOf(cl, name);


1721             } catch (IllegalArgumentException ex) {
1722                 throw (IOException) new InvalidObjectException(
1723                     "enum constant " + name + " does not exist in " +
1724                     cl).initCause(ex);
1725             }
1726             if (!unshared) {
1727                 handles.setObject(enumHandle, en);
1728             }
1729         }
1730 
1731         handles.finish(enumHandle);
1732         passHandle = enumHandle;
1733         return en;
1734     }
1735 
1736     /**
1737      * Reads and returns "ordinary" (i.e., not a String, Class,
1738      * ObjectStreamClass, array, or enum constant) object, or null if object's
1739      * class is unresolvable (in which case a ClassNotFoundException will be
1740      * associated with object's handle).  Sets passHandle to object's assigned
1741      * handle.
1742      */
1743     private Object readOrdinaryObject(boolean unshared)
1744         throws IOException
1745     {
1746         if (bin.readByte() != TC_OBJECT) {
1747             throw new InternalError();
1748         }
1749 
1750         ObjectStreamClass desc = readClassDesc(false);
1751         desc.checkDeserialize();
1752 
1753         Object obj;


1924                     bin.readByte();
1925                     passHandle = oldHandle;
1926                     return;
1927 
1928                 default:
1929                     readObject0(false);
1930                     break;
1931             }
1932         }
1933     }
1934 
1935     /**
1936      * Reads in values of serializable fields declared by given class
1937      * descriptor.  If obj is non-null, sets field values in obj.  Expects that
1938      * passHandle is set to obj's handle before this method is called.
1939      */
1940     private void defaultReadFields(Object obj, ObjectStreamClass desc)
1941         throws IOException
1942     {
1943         // REMIND: is isInstance check necessary?
1944         Class cl = desc.forClass();
1945         if (cl != null && obj != null && !cl.isInstance(obj)) {
1946             throw new ClassCastException();
1947         }
1948 
1949         int primDataSize = desc.getPrimDataSize();
1950         if (primVals == null || primVals.length < primDataSize) {
1951             primVals = new byte[primDataSize];
1952         }
1953         bin.readFully(primVals, 0, primDataSize, false);
1954         if (obj != null) {
1955             desc.setPrimFieldValues(obj, primVals);
1956         }
1957 
1958         int objHandle = passHandle;
1959         ObjectStreamField[] fields = desc.getFields(false);
1960         Object[] objVals = new Object[desc.getNumObjFields()];
1961         int numPrimFields = fields.length - objVals.length;
1962         for (int i = 0; i < objVals.length; i++) {
1963             ObjectStreamField f = fields[numPrimFields + i];
1964             objVals[i] = readObject0(f.isUnshared());


2123             int oldHandle = passHandle;
2124             ObjectStreamField[] fields = desc.getFields(false);
2125             int numPrimFields = fields.length - objVals.length;
2126             for (int i = 0; i < objVals.length; i++) {
2127                 objVals[i] =
2128                     readObject0(fields[numPrimFields + i].isUnshared());
2129                 objHandles[i] = passHandle;
2130             }
2131             passHandle = oldHandle;
2132         }
2133 
2134         /**
2135          * Returns offset of field with given name and type.  A specified type
2136          * of null matches all types, Object.class matches all non-primitive
2137          * types, and any other non-null type matches assignable types only.
2138          * If no matching field is found in the (incoming) class
2139          * descriptor but a matching field is present in the associated local
2140          * class descriptor, returns -1.  Throws IllegalArgumentException if
2141          * neither incoming nor local class descriptor contains a match.
2142          */
2143         private int getFieldOffset(String name, Class type) {
2144             ObjectStreamField field = desc.getField(name, type);
2145             if (field != null) {
2146                 return field.getOffset();
2147             } else if (desc.getLocalDesc().getField(name, type) != null) {
2148                 return -1;
2149             } else {
2150                 throw new IllegalArgumentException("no such field " + name +
2151                                                    " with type " + type);
2152             }
2153         }
2154     }
2155 
2156     /**
2157      * Prioritized list of callbacks to be performed once object graph has been
2158      * completely deserialized.
2159      */
2160     private static class ValidationList {
2161 
2162         private static class Callback {
2163             final ObjectInputValidation obj;


2821             pos += 8;
2822             return v;
2823         }
2824 
2825         public double readDouble() throws IOException {
2826             if (!blkmode) {
2827                 pos = 0;
2828                 in.readFully(buf, 0, 8);
2829             } else if (end - pos < 8) {
2830                 return din.readDouble();
2831             }
2832             double v = Bits.getDouble(buf, pos);
2833             pos += 8;
2834             return v;
2835         }
2836 
2837         public String readUTF() throws IOException {
2838             return readUTFBody(readUnsignedShort());
2839         }
2840 

2841         public String readLine() throws IOException {
2842             return din.readLine();      // deprecated, not worth optimizing
2843         }
2844 
2845         /* -------------- primitive data array input methods --------------- */
2846         /*
2847          * The following methods read in spans of primitive data values.
2848          * Though equivalent to calling the corresponding primitive read
2849          * methods repeatedly, these methods are optimized for reading groups
2850          * of primitive data values more efficiently.
2851          */
2852 
2853         void readBooleans(boolean[] v, int off, int len) throws IOException {
2854             int stop, endoff = off + len;
2855             while (off < endoff) {
2856                 if (!blkmode) {
2857                     int span = Math.min(endoff - off, MAX_BLOCK_SIZE);
2858                     in.readFully(buf, 0, span);
2859                     stop = off + span;
2860                     pos = 0;




 672      * <code>IllegalArgumentException</code>.
 673      *
 674      * @param interfaces the list of interface names that were
 675      *                deserialized in the proxy class descriptor
 676      * @return  a proxy class for the specified interfaces
 677      * @throws        IOException any exception thrown by the underlying
 678      *                <code>InputStream</code>
 679      * @throws        ClassNotFoundException if the proxy class or any of the
 680      *                named interfaces could not be found
 681      * @see ObjectOutputStream#annotateProxyClass(Class)
 682      * @since 1.3
 683      */
 684     protected Class<?> resolveProxyClass(String[] interfaces)
 685         throws IOException, ClassNotFoundException
 686     {
 687         ClassLoader latestLoader = latestUserDefinedLoader();
 688         ClassLoader nonPublicLoader = null;
 689         boolean hasNonPublicInterface = false;
 690 
 691         // define proxy in class loader of non-public interface(s), if any
 692         Class<?>[] classObjs = new Class<?>[interfaces.length];
 693         for (int i = 0; i < interfaces.length; i++) {
 694             Class<?> cl = Class.forName(interfaces[i], false, latestLoader);
 695             if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {
 696                 if (hasNonPublicInterface) {
 697                     if (nonPublicLoader != cl.getClassLoader()) {
 698                         throw new IllegalAccessError(
 699                             "conflicting non-public interface class loaders");
 700                     }
 701                 } else {
 702                     nonPublicLoader = cl.getClassLoader();
 703                     hasNonPublicInterface = true;
 704                 }
 705             }
 706             classObjs[i] = cl;
 707         }
 708         try {
 709             return Proxy.getProxyClass(
 710                 hasNonPublicInterface ? nonPublicLoader : latestLoader,
 711                 classObjs);
 712         } catch (IllegalArgumentException e) {
 713             throw new ClassNotFoundException(null, e);
 714         }


1212          *
1213          * @param  name the name of the field
1214          * @param  val the default value to use if <code>name</code> does not
1215          *         have a value
1216          * @return the value of the named <code>Object</code> field
1217          * @throws IOException if there are I/O errors while reading from the
1218          *         underlying <code>InputStream</code>
1219          * @throws IllegalArgumentException if type of <code>name</code> is
1220          *         not serializable or if the field type is incorrect
1221          */
1222         public abstract Object get(String name, Object val) throws IOException;
1223     }
1224 
1225     /**
1226      * Verifies that this (possibly subclass) instance can be constructed
1227      * without violating security constraints: the subclass must not override
1228      * security-sensitive non-final methods, or else the
1229      * "enableSubclassImplementation" SerializablePermission is checked.
1230      */
1231     private void verifySubclass() {
1232         Class<?> cl = getClass();
1233         if (cl == ObjectInputStream.class) {
1234             return;
1235         }
1236         SecurityManager sm = System.getSecurityManager();
1237         if (sm == null) {
1238             return;
1239         }
1240         processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);
1241         WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);
1242         Boolean result = Caches.subclassAudits.get(key);
1243         if (result == null) {
1244             result = Boolean.valueOf(auditSubclass(cl));
1245             Caches.subclassAudits.putIfAbsent(key, result);
1246         }
1247         if (result.booleanValue()) {
1248             return;
1249         }
1250         sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
1251     }
1252 


1456             // REMIND: what type of exception to throw here?
1457             throw new InvalidObjectException(
1458                 "cannot read back reference as unshared");
1459         }
1460 
1461         Object obj = handles.lookupObject(passHandle);
1462         if (obj == unsharedMarker) {
1463             // REMIND: what type of exception to throw here?
1464             throw new InvalidObjectException(
1465                 "cannot read back reference to unshared object");
1466         }
1467         return obj;
1468     }
1469 
1470     /**
1471      * Reads in and returns class object.  Sets passHandle to class object's
1472      * assigned handle.  Returns null if class is unresolvable (in which case a
1473      * ClassNotFoundException will be associated with the class' handle in the
1474      * handle table).
1475      */
1476     private Class<?> readClass(boolean unshared) throws IOException {
1477         if (bin.readByte() != TC_CLASS) {
1478             throw new InternalError();
1479         }
1480         ObjectStreamClass desc = readClassDesc(false);
1481         Class<?> cl = desc.forClass();
1482         passHandle = handles.assign(unshared ? unsharedMarker : cl);
1483 
1484         ClassNotFoundException resolveEx = desc.getResolveException();
1485         if (resolveEx != null) {
1486             handles.markException(passHandle, resolveEx);
1487         }
1488 
1489         handles.finish(passHandle);
1490         return cl;
1491     }
1492 
1493     /**
1494      * Reads in and returns (possibly null) class descriptor.  Sets passHandle
1495      * to class descriptor's assigned handle.  If class descriptor cannot be
1496      * resolved to a class in the local VM, a ClassNotFoundException is
1497      * associated with the class descriptor's handle.
1498      */
1499     private ObjectStreamClass readClassDesc(boolean unshared)
1500         throws IOException
1501     {


1525      * descriptor cannot be resolved to a class in the local VM, a
1526      * ClassNotFoundException is associated with the descriptor's handle.
1527      */
1528     private ObjectStreamClass readProxyDesc(boolean unshared)
1529         throws IOException
1530     {
1531         if (bin.readByte() != TC_PROXYCLASSDESC) {
1532             throw new InternalError();
1533         }
1534 
1535         ObjectStreamClass desc = new ObjectStreamClass();
1536         int descHandle = handles.assign(unshared ? unsharedMarker : desc);
1537         passHandle = NULL_HANDLE;
1538 
1539         int numIfaces = bin.readInt();
1540         String[] ifaces = new String[numIfaces];
1541         for (int i = 0; i < numIfaces; i++) {
1542             ifaces[i] = bin.readUTF();
1543         }
1544 
1545         Class<?> cl = null;
1546         ClassNotFoundException resolveEx = null;
1547         bin.setBlockDataMode(true);
1548         try {
1549             if ((cl = resolveProxyClass(ifaces)) == null) {
1550                 resolveEx = new ClassNotFoundException("null class");
1551             }
1552         } catch (ClassNotFoundException ex) {
1553             resolveEx = ex;
1554         }
1555         skipCustomData();
1556 
1557         desc.initProxy(cl, resolveEx, readClassDesc(false));
1558 
1559         handles.finish(descHandle);
1560         passHandle = descHandle;
1561         return desc;
1562     }
1563 
1564     /**
1565      * Reads in and returns class descriptor for a class that is not a dynamic


1569      */
1570     private ObjectStreamClass readNonProxyDesc(boolean unshared)
1571         throws IOException
1572     {
1573         if (bin.readByte() != TC_CLASSDESC) {
1574             throw new InternalError();
1575         }
1576 
1577         ObjectStreamClass desc = new ObjectStreamClass();
1578         int descHandle = handles.assign(unshared ? unsharedMarker : desc);
1579         passHandle = NULL_HANDLE;
1580 
1581         ObjectStreamClass readDesc = null;
1582         try {
1583             readDesc = readClassDescriptor();
1584         } catch (ClassNotFoundException ex) {
1585             throw (IOException) new InvalidClassException(
1586                 "failed to read class descriptor").initCause(ex);
1587         }
1588 
1589         Class<?> cl = null;
1590         ClassNotFoundException resolveEx = null;
1591         bin.setBlockDataMode(true);
1592         try {
1593             if ((cl = resolveClass(readDesc)) == null) {
1594                 resolveEx = new ClassNotFoundException("null class");
1595             }
1596         } catch (ClassNotFoundException ex) {
1597             resolveEx = ex;
1598         }
1599         skipCustomData();
1600 
1601         desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false));
1602 
1603         handles.finish(descHandle);
1604         passHandle = descHandle;
1605         return desc;
1606     }
1607 
1608     /**
1609      * Reads in and returns new string.  Sets passHandle to new string's


1626                     String.format("invalid type code: %02X", tc));
1627         }
1628         passHandle = handles.assign(unshared ? unsharedMarker : str);
1629         handles.finish(passHandle);
1630         return str;
1631     }
1632 
1633     /**
1634      * Reads in and returns array object, or null if array class is
1635      * unresolvable.  Sets passHandle to array's assigned handle.
1636      */
1637     private Object readArray(boolean unshared) throws IOException {
1638         if (bin.readByte() != TC_ARRAY) {
1639             throw new InternalError();
1640         }
1641 
1642         ObjectStreamClass desc = readClassDesc(false);
1643         int len = bin.readInt();
1644 
1645         Object array = null;
1646         Class<?> cl, ccl = null;
1647         if ((cl = desc.forClass()) != null) {
1648             ccl = cl.getComponentType();
1649             array = Array.newInstance(ccl, len);
1650         }
1651 
1652         int arrayHandle = handles.assign(unshared ? unsharedMarker : array);
1653         ClassNotFoundException resolveEx = desc.getResolveException();
1654         if (resolveEx != null) {
1655             handles.markException(arrayHandle, resolveEx);
1656         }
1657 
1658         if (ccl == null) {
1659             for (int i = 0; i < len; i++) {
1660                 readObject0(false);
1661             }
1662         } else if (ccl.isPrimitive()) {
1663             if (ccl == Integer.TYPE) {
1664                 bin.readInts((int[]) array, 0, len);
1665             } else if (ccl == Byte.TYPE) {
1666                 bin.readFully((byte[]) array, 0, len, true);


1679             } else {
1680                 throw new InternalError();
1681             }
1682         } else {
1683             Object[] oa = (Object[]) array;
1684             for (int i = 0; i < len; i++) {
1685                 oa[i] = readObject0(false);
1686                 handles.markDependency(arrayHandle, passHandle);
1687             }
1688         }
1689 
1690         handles.finish(arrayHandle);
1691         passHandle = arrayHandle;
1692         return array;
1693     }
1694 
1695     /**
1696      * Reads in and returns enum constant, or null if enum type is
1697      * unresolvable.  Sets passHandle to enum constant's assigned handle.
1698      */
1699     private Enum<?> readEnum(boolean unshared) throws IOException {
1700         if (bin.readByte() != TC_ENUM) {
1701             throw new InternalError();
1702         }
1703 
1704         ObjectStreamClass desc = readClassDesc(false);
1705         if (!desc.isEnum()) {
1706             throw new InvalidClassException("non-enum class: " + desc);
1707         }
1708 
1709         int enumHandle = handles.assign(unshared ? unsharedMarker : null);
1710         ClassNotFoundException resolveEx = desc.getResolveException();
1711         if (resolveEx != null) {
1712             handles.markException(enumHandle, resolveEx);
1713         }
1714 
1715         String name = readString(false);
1716         Enum<?> result = null;
1717         Class<?> cl = desc.forClass();
1718         if (cl != null) {
1719             try {
1720                 @SuppressWarnings("unchecked")
1721                 Enum<?> en = Enum.valueOf((Class)cl, name);
1722                 result = en;
1723             } catch (IllegalArgumentException ex) {
1724                 throw (IOException) new InvalidObjectException(
1725                     "enum constant " + name + " does not exist in " +
1726                     cl).initCause(ex);
1727             }
1728             if (!unshared) {
1729                 handles.setObject(enumHandle, result);
1730             }
1731         }
1732 
1733         handles.finish(enumHandle);
1734         passHandle = enumHandle;
1735         return result;
1736     }
1737 
1738     /**
1739      * Reads and returns "ordinary" (i.e., not a String, Class,
1740      * ObjectStreamClass, array, or enum constant) object, or null if object's
1741      * class is unresolvable (in which case a ClassNotFoundException will be
1742      * associated with object's handle).  Sets passHandle to object's assigned
1743      * handle.
1744      */
1745     private Object readOrdinaryObject(boolean unshared)
1746         throws IOException
1747     {
1748         if (bin.readByte() != TC_OBJECT) {
1749             throw new InternalError();
1750         }
1751 
1752         ObjectStreamClass desc = readClassDesc(false);
1753         desc.checkDeserialize();
1754 
1755         Object obj;


1926                     bin.readByte();
1927                     passHandle = oldHandle;
1928                     return;
1929 
1930                 default:
1931                     readObject0(false);
1932                     break;
1933             }
1934         }
1935     }
1936 
1937     /**
1938      * Reads in values of serializable fields declared by given class
1939      * descriptor.  If obj is non-null, sets field values in obj.  Expects that
1940      * passHandle is set to obj's handle before this method is called.
1941      */
1942     private void defaultReadFields(Object obj, ObjectStreamClass desc)
1943         throws IOException
1944     {
1945         // REMIND: is isInstance check necessary?
1946         Class<?> cl = desc.forClass();
1947         if (cl != null && obj != null && !cl.isInstance(obj)) {
1948             throw new ClassCastException();
1949         }
1950 
1951         int primDataSize = desc.getPrimDataSize();
1952         if (primVals == null || primVals.length < primDataSize) {
1953             primVals = new byte[primDataSize];
1954         }
1955         bin.readFully(primVals, 0, primDataSize, false);
1956         if (obj != null) {
1957             desc.setPrimFieldValues(obj, primVals);
1958         }
1959 
1960         int objHandle = passHandle;
1961         ObjectStreamField[] fields = desc.getFields(false);
1962         Object[] objVals = new Object[desc.getNumObjFields()];
1963         int numPrimFields = fields.length - objVals.length;
1964         for (int i = 0; i < objVals.length; i++) {
1965             ObjectStreamField f = fields[numPrimFields + i];
1966             objVals[i] = readObject0(f.isUnshared());


2125             int oldHandle = passHandle;
2126             ObjectStreamField[] fields = desc.getFields(false);
2127             int numPrimFields = fields.length - objVals.length;
2128             for (int i = 0; i < objVals.length; i++) {
2129                 objVals[i] =
2130                     readObject0(fields[numPrimFields + i].isUnshared());
2131                 objHandles[i] = passHandle;
2132             }
2133             passHandle = oldHandle;
2134         }
2135 
2136         /**
2137          * Returns offset of field with given name and type.  A specified type
2138          * of null matches all types, Object.class matches all non-primitive
2139          * types, and any other non-null type matches assignable types only.
2140          * If no matching field is found in the (incoming) class
2141          * descriptor but a matching field is present in the associated local
2142          * class descriptor, returns -1.  Throws IllegalArgumentException if
2143          * neither incoming nor local class descriptor contains a match.
2144          */
2145         private int getFieldOffset(String name, Class<?> type) {
2146             ObjectStreamField field = desc.getField(name, type);
2147             if (field != null) {
2148                 return field.getOffset();
2149             } else if (desc.getLocalDesc().getField(name, type) != null) {
2150                 return -1;
2151             } else {
2152                 throw new IllegalArgumentException("no such field " + name +
2153                                                    " with type " + type);
2154             }
2155         }
2156     }
2157 
2158     /**
2159      * Prioritized list of callbacks to be performed once object graph has been
2160      * completely deserialized.
2161      */
2162     private static class ValidationList {
2163 
2164         private static class Callback {
2165             final ObjectInputValidation obj;


2823             pos += 8;
2824             return v;
2825         }
2826 
2827         public double readDouble() throws IOException {
2828             if (!blkmode) {
2829                 pos = 0;
2830                 in.readFully(buf, 0, 8);
2831             } else if (end - pos < 8) {
2832                 return din.readDouble();
2833             }
2834             double v = Bits.getDouble(buf, pos);
2835             pos += 8;
2836             return v;
2837         }
2838 
2839         public String readUTF() throws IOException {
2840             return readUTFBody(readUnsignedShort());
2841         }
2842 
2843         @SuppressWarnings("deprecation")
2844         public String readLine() throws IOException {
2845             return din.readLine();      // deprecated, not worth optimizing
2846         }
2847 
2848         /* -------------- primitive data array input methods --------------- */
2849         /*
2850          * The following methods read in spans of primitive data values.
2851          * Though equivalent to calling the corresponding primitive read
2852          * methods repeatedly, these methods are optimized for reading groups
2853          * of primitive data values more efficiently.
2854          */
2855 
2856         void readBooleans(boolean[] v, int off, int len) throws IOException {
2857             int stop, endoff = off + len;
2858             while (off < endoff) {
2859                 if (!blkmode) {
2860                     int span = Math.min(endoff - off, MAX_BLOCK_SIZE);
2861                     in.readFully(buf, 0, span);
2862                     stop = off + span;
2863                     pos = 0;