< prev index next >

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

Print this page
rev 12533 : 8174109: Better queuing priorities
Reviewed-by: smarks
rev 12550 : 8181597: Process Proxy presentation
Reviewed-by: dfuchs, ahgross, rhalade, skoivu


  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.Objects;
  41 import java.util.concurrent.ConcurrentHashMap;
  42 import java.util.concurrent.ConcurrentMap;
  43 
  44 import static java.io.ObjectStreamClass.processQueue;
  45 

  46 import sun.misc.ObjectInputFilter;
  47 import sun.misc.ObjectStreamClassValidator;
  48 import sun.misc.SharedSecrets;
  49 import sun.reflect.misc.ReflectUtil;
  50 import sun.misc.JavaOISAccess;
  51 import sun.util.logging.PlatformLogger;
  52 
  53 /**
  54  * An ObjectInputStream deserializes primitive data and objects previously
  55  * written using an ObjectOutputStream.
  56  *
  57  * <p>ObjectOutputStream and ObjectInputStream can provide an application with
  58  * persistent storage for graphs of objects when used with a FileOutputStream
  59  * and FileInputStream respectively.  ObjectInputStream is used to recover
  60  * those objects previously serialized. Other uses include passing objects
  61  * between hosts using a socket stream or for marshaling and unmarshaling
  62  * arguments and parameters in a remote communication system.
  63  *
  64  * <p>ObjectInputStream ensures that the types of all objects in the graph
  65  * created from the stream match the classes present in the Java Virtual


 237     private static class Caches {
 238         /** cache of subclass security audit results */
 239         static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits =
 240             new ConcurrentHashMap<>();
 241 
 242         /** queue for WeakReferences to audited subclasses */
 243         static final ReferenceQueue<Class<?>> subclassAuditsQueue =
 244             new ReferenceQueue<>();
 245     }
 246 
 247     static {
 248         /* Setup access so sun.misc can invoke package private functions. */
 249         sun.misc.SharedSecrets.setJavaOISAccess(new JavaOISAccess() {
 250             public void setObjectInputFilter(ObjectInputStream stream, ObjectInputFilter filter) {
 251                 stream.setInternalObjectInputFilter(filter);
 252             }
 253 
 254             public ObjectInputFilter getObjectInputFilter(ObjectInputStream stream) {
 255                 return stream.getInternalObjectInputFilter();
 256             }










 257         });
 258     }
 259 
 260     /*
 261      * Separate class to defer initialization of logging until needed.
 262      */
 263     private static class Logging {
 264 
 265         /*
 266          * Logger for ObjectInputFilter results.
 267          * Setup the filter logger if it is set to INFO or WARNING.
 268          * (Assuming it will not change).
 269          */
 270         private static final PlatformLogger traceLogger;
 271         private static final PlatformLogger infoLogger;
 272         static {
 273             PlatformLogger filterLog = PlatformLogger.getLogger("java.io.serialization");
 274             infoLogger = (filterLog != null &&
 275                 filterLog.isLoggable(PlatformLogger.Level.INFO)) ? filterLog : null;
 276             traceLogger = (filterLog != null &&


1240                             "ObjectInputFilter {0}: {1}, array length: {2}, nRefs: {3}, depth: {4}, bytes: {5}, ex: {6}",
1241                             status, clazz, arrayLength, totalObjectRefs, depth, bin.getBytesRead(),
1242                             Objects.toString(ex, "n/a"));
1243                 }
1244                 InvalidClassException ice = new InvalidClassException("filter status: " + status);
1245                 ice.initCause(ex);
1246                 throw ice;
1247             } else {
1248                 // Trace logging for those that succeed
1249                 if (Logging.traceLogger != null) {
1250                     Logging.traceLogger.finer(
1251                             "ObjectInputFilter {0}: {1}, array length: {2}, nRefs: {3}, depth: {4}, bytes: {5}, ex: {6}",
1252                             status, clazz, arrayLength, totalObjectRefs, depth, bin.getBytesRead(),
1253                             Objects.toString(ex, "n/a"));
1254                 }
1255             }
1256         }
1257     }
1258 
1259     /**



























1260      * Provide access to the persistent fields read from the input stream.
1261      */
1262     public static abstract class GetField {
1263 
1264         /**
1265          * Get the ObjectStreamClass that describes the fields in the stream.
1266          *
1267          * @return  the descriptor class that describes the serializable fields
1268          */
1269         public abstract ObjectStreamClass getObjectStreamClass();
1270 
1271         /**
1272          * Return true if the named field is defaulted and has no value in this
1273          * stream.
1274          *
1275          * @param  name the name of the field
1276          * @return true, if and only if the named field is defaulted
1277          * @throws IOException if there are I/O errors while reading from
1278          *         the underlying <code>InputStream</code>
1279          * @throws IllegalArgumentException if <code>name</code> does not


1729     }
1730 
1731     /**
1732      * Reads in and returns class descriptor for a dynamic proxy class.  Sets
1733      * passHandle to proxy class descriptor's assigned handle.  If proxy class
1734      * descriptor cannot be resolved to a class in the local VM, a
1735      * ClassNotFoundException is associated with the descriptor's handle.
1736      */
1737     private ObjectStreamClass readProxyDesc(boolean unshared)
1738         throws IOException
1739     {
1740         if (bin.readByte() != TC_PROXYCLASSDESC) {
1741             throw new InternalError();
1742         }
1743 
1744         ObjectStreamClass desc = new ObjectStreamClass();
1745         int descHandle = handles.assign(unshared ? unsharedMarker : desc);
1746         passHandle = NULL_HANDLE;
1747 
1748         int numIfaces = bin.readInt();




1749         String[] ifaces = new String[numIfaces];
1750         for (int i = 0; i < numIfaces; i++) {
1751             ifaces[i] = bin.readUTF();
1752         }
1753 
1754         Class<?> cl = null;
1755         ClassNotFoundException resolveEx = null;
1756         bin.setBlockDataMode(true);
1757         try {
1758             if ((cl = resolveProxyClass(ifaces)) == null) {
1759                 resolveEx = new ClassNotFoundException("null class");
1760             } else if (!Proxy.isProxyClass(cl)) {
1761                 throw new InvalidClassException("Not a proxy");
1762             } else {
1763                 // ReflectUtil.checkProxyPackageAccess makes a test
1764                 // equivalent to isCustomSubclass so there's no need
1765                 // to condition this call to isCustomSubclass == true here.
1766                 ReflectUtil.checkProxyPackageAccess(
1767                         getClass().getClassLoader(),
1768                         cl.getInterfaces());


3852         } else if (array instanceof int[]) {
3853             return ((int[]) array).clone();
3854         } else if (array instanceof long[]) {
3855             return ((long[]) array).clone();
3856         } else if (array instanceof short[]) {
3857             return ((short[]) array).clone();
3858         } else {
3859             throw new AssertionError();
3860         }
3861     }
3862 
3863     private void validateDescriptor(ObjectStreamClass descriptor) {
3864         ObjectStreamClassValidator validating = validator;
3865         if (validating != null) {
3866             validating.validateDescriptor(descriptor);
3867         }
3868     }
3869 
3870     // controlled access to ObjectStreamClassValidator
3871     private volatile ObjectStreamClassValidator validator;
3872 
3873     private static void setValidator(ObjectInputStream ois, ObjectStreamClassValidator validator) {
3874         ois.validator = validator;
3875     }
3876     static {
3877         SharedSecrets.setJavaObjectInputStreamAccess(ObjectInputStream::setValidator);
3878     }
3879 }


  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.Objects;
  41 import java.util.concurrent.ConcurrentHashMap;
  42 import java.util.concurrent.ConcurrentMap;
  43 
  44 import static java.io.ObjectStreamClass.processQueue;
  45 
  46 import sun.misc.SharedSecrets;
  47 import sun.misc.ObjectInputFilter;
  48 import sun.misc.ObjectStreamClassValidator;
  49 import sun.misc.SharedSecrets;
  50 import sun.reflect.misc.ReflectUtil;
  51 import sun.misc.JavaOISAccess;
  52 import sun.util.logging.PlatformLogger;
  53 
  54 /**
  55  * An ObjectInputStream deserializes primitive data and objects previously
  56  * written using an ObjectOutputStream.
  57  *
  58  * <p>ObjectOutputStream and ObjectInputStream can provide an application with
  59  * persistent storage for graphs of objects when used with a FileOutputStream
  60  * and FileInputStream respectively.  ObjectInputStream is used to recover
  61  * those objects previously serialized. Other uses include passing objects
  62  * between hosts using a socket stream or for marshaling and unmarshaling
  63  * arguments and parameters in a remote communication system.
  64  *
  65  * <p>ObjectInputStream ensures that the types of all objects in the graph
  66  * created from the stream match the classes present in the Java Virtual


 238     private static class Caches {
 239         /** cache of subclass security audit results */
 240         static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits =
 241             new ConcurrentHashMap<>();
 242 
 243         /** queue for WeakReferences to audited subclasses */
 244         static final ReferenceQueue<Class<?>> subclassAuditsQueue =
 245             new ReferenceQueue<>();
 246     }
 247 
 248     static {
 249         /* Setup access so sun.misc can invoke package private functions. */
 250         sun.misc.SharedSecrets.setJavaOISAccess(new JavaOISAccess() {
 251             public void setObjectInputFilter(ObjectInputStream stream, ObjectInputFilter filter) {
 252                 stream.setInternalObjectInputFilter(filter);
 253             }
 254 
 255             public ObjectInputFilter getObjectInputFilter(ObjectInputStream stream) {
 256                 return stream.getInternalObjectInputFilter();
 257             }
 258 
 259             public void checkArray(ObjectInputStream stream, Class<?> arrayType, int arrayLength)
 260                 throws InvalidClassException
 261             {
 262                 stream.checkArray(arrayType, arrayLength);
 263             }
 264 
 265             public void setValidator(ObjectInputStream ois, ObjectStreamClassValidator validator) {
 266                 ois.validator = validator;
 267             }
 268         });
 269     }
 270 
 271     /*
 272      * Separate class to defer initialization of logging until needed.
 273      */
 274     private static class Logging {
 275 
 276         /*
 277          * Logger for ObjectInputFilter results.
 278          * Setup the filter logger if it is set to INFO or WARNING.
 279          * (Assuming it will not change).
 280          */
 281         private static final PlatformLogger traceLogger;
 282         private static final PlatformLogger infoLogger;
 283         static {
 284             PlatformLogger filterLog = PlatformLogger.getLogger("java.io.serialization");
 285             infoLogger = (filterLog != null &&
 286                 filterLog.isLoggable(PlatformLogger.Level.INFO)) ? filterLog : null;
 287             traceLogger = (filterLog != null &&


1251                             "ObjectInputFilter {0}: {1}, array length: {2}, nRefs: {3}, depth: {4}, bytes: {5}, ex: {6}",
1252                             status, clazz, arrayLength, totalObjectRefs, depth, bin.getBytesRead(),
1253                             Objects.toString(ex, "n/a"));
1254                 }
1255                 InvalidClassException ice = new InvalidClassException("filter status: " + status);
1256                 ice.initCause(ex);
1257                 throw ice;
1258             } else {
1259                 // Trace logging for those that succeed
1260                 if (Logging.traceLogger != null) {
1261                     Logging.traceLogger.finer(
1262                             "ObjectInputFilter {0}: {1}, array length: {2}, nRefs: {3}, depth: {4}, bytes: {5}, ex: {6}",
1263                             status, clazz, arrayLength, totalObjectRefs, depth, bin.getBytesRead(),
1264                             Objects.toString(ex, "n/a"));
1265                 }
1266             }
1267         }
1268     }
1269 
1270     /**
1271      * Checks the given array type and length to ensure that creation of such
1272      * an array is permitted by this ObjectInputStream. The arrayType argument
1273      * must represent an actual array type.
1274      *
1275      * This private method is called via SharedSecrets.
1276      *
1277      * @param arrayType the array type
1278      * @param arrayLength the array length
1279      * @throws NullPointerException if arrayType is null
1280      * @throws IllegalArgumentException if arrayType isn't actually an array type
1281      * @throws NegativeArraySizeException if arrayLength is negative
1282      * @throws InvalidClassException if the filter rejects creation
1283      */
1284     private void checkArray(Class<?> arrayType, int arrayLength) throws InvalidClassException {
1285         Objects.requireNonNull(arrayType);
1286         if (! arrayType.isArray()) {
1287             throw new IllegalArgumentException("not an array type");
1288         }
1289 
1290         if (arrayLength < 0) {
1291             throw new NegativeArraySizeException();
1292         }
1293 
1294         filterCheck(arrayType, arrayLength);
1295     }
1296 
1297     /**
1298      * Provide access to the persistent fields read from the input stream.
1299      */
1300     public static abstract class GetField {
1301 
1302         /**
1303          * Get the ObjectStreamClass that describes the fields in the stream.
1304          *
1305          * @return  the descriptor class that describes the serializable fields
1306          */
1307         public abstract ObjectStreamClass getObjectStreamClass();
1308 
1309         /**
1310          * Return true if the named field is defaulted and has no value in this
1311          * stream.
1312          *
1313          * @param  name the name of the field
1314          * @return true, if and only if the named field is defaulted
1315          * @throws IOException if there are I/O errors while reading from
1316          *         the underlying <code>InputStream</code>
1317          * @throws IllegalArgumentException if <code>name</code> does not


1767     }
1768 
1769     /**
1770      * Reads in and returns class descriptor for a dynamic proxy class.  Sets
1771      * passHandle to proxy class descriptor's assigned handle.  If proxy class
1772      * descriptor cannot be resolved to a class in the local VM, a
1773      * ClassNotFoundException is associated with the descriptor's handle.
1774      */
1775     private ObjectStreamClass readProxyDesc(boolean unshared)
1776         throws IOException
1777     {
1778         if (bin.readByte() != TC_PROXYCLASSDESC) {
1779             throw new InternalError();
1780         }
1781 
1782         ObjectStreamClass desc = new ObjectStreamClass();
1783         int descHandle = handles.assign(unshared ? unsharedMarker : desc);
1784         passHandle = NULL_HANDLE;
1785 
1786         int numIfaces = bin.readInt();
1787         if (numIfaces > 65535) {
1788             throw new InvalidObjectException("interface limit exceeded: "
1789                     + numIfaces);
1790         }
1791         String[] ifaces = new String[numIfaces];
1792         for (int i = 0; i < numIfaces; i++) {
1793             ifaces[i] = bin.readUTF();
1794         }
1795 
1796         Class<?> cl = null;
1797         ClassNotFoundException resolveEx = null;
1798         bin.setBlockDataMode(true);
1799         try {
1800             if ((cl = resolveProxyClass(ifaces)) == null) {
1801                 resolveEx = new ClassNotFoundException("null class");
1802             } else if (!Proxy.isProxyClass(cl)) {
1803                 throw new InvalidClassException("Not a proxy");
1804             } else {
1805                 // ReflectUtil.checkProxyPackageAccess makes a test
1806                 // equivalent to isCustomSubclass so there's no need
1807                 // to condition this call to isCustomSubclass == true here.
1808                 ReflectUtil.checkProxyPackageAccess(
1809                         getClass().getClassLoader(),
1810                         cl.getInterfaces());


3894         } else if (array instanceof int[]) {
3895             return ((int[]) array).clone();
3896         } else if (array instanceof long[]) {
3897             return ((long[]) array).clone();
3898         } else if (array instanceof short[]) {
3899             return ((short[]) array).clone();
3900         } else {
3901             throw new AssertionError();
3902         }
3903     }
3904 
3905     private void validateDescriptor(ObjectStreamClass descriptor) {
3906         ObjectStreamClassValidator validating = validator;
3907         if (validating != null) {
3908             validating.validateDescriptor(descriptor);
3909         }
3910     }
3911 
3912     // controlled access to ObjectStreamClassValidator
3913     private volatile ObjectStreamClassValidator validator;







3914 }
< prev index next >