src/java.base/share/classes/java/io/ObjectOutputStream.java
branchdatagramsocketimpl-branch
changeset 58678 9cf78a70fa4f
parent 47216 71c04702a3d5
child 58679 9c3209ff7550
equal deleted inserted replaced
58677:13588c901957 58678:9cf78a70fa4f
     1 /*
     1 /*
     2  * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
   230      *
   230      *
   231      * @param   out output stream to write to
   231      * @param   out output stream to write to
   232      * @throws  IOException if an I/O error occurs while writing stream header
   232      * @throws  IOException if an I/O error occurs while writing stream header
   233      * @throws  SecurityException if untrusted subclass illegally overrides
   233      * @throws  SecurityException if untrusted subclass illegally overrides
   234      *          security-sensitive methods
   234      *          security-sensitive methods
   235      * @throws  NullPointerException if <code>out</code> is <code>null</code>
   235      * @throws  NullPointerException if {@code out} is {@code null}
   236      * @since   1.4
   236      * @since   1.4
   237      * @see     ObjectOutputStream#ObjectOutputStream()
   237      * @see     ObjectOutputStream#ObjectOutputStream()
   238      * @see     ObjectOutputStream#putFields()
   238      * @see     ObjectOutputStream#putFields()
   239      * @see     ObjectInputStream#ObjectInputStream(InputStream)
   239      * @see     ObjectInputStream#ObjectInputStream(InputStream)
   240      */
   240      */
   257      * Provide a way for subclasses that are completely reimplementing
   257      * Provide a way for subclasses that are completely reimplementing
   258      * ObjectOutputStream to not have to allocate private data just used by
   258      * ObjectOutputStream to not have to allocate private data just used by
   259      * this implementation of ObjectOutputStream.
   259      * this implementation of ObjectOutputStream.
   260      *
   260      *
   261      * <p>If there is a security manager installed, this method first calls the
   261      * <p>If there is a security manager installed, this method first calls the
   262      * security manager's <code>checkPermission</code> method with a
   262      * security manager's {@code checkPermission} method with a
   263      * <code>SerializablePermission("enableSubclassImplementation")</code>
   263      * {@code SerializablePermission("enableSubclassImplementation")}
   264      * permission to ensure it's ok to enable subclassing.
   264      * permission to ensure it's ok to enable subclassing.
   265      *
   265      *
   266      * @throws  SecurityException if a security manager exists and its
   266      * @throws  SecurityException if a security manager exists and its
   267      *          <code>checkPermission</code> method denies enabling
   267      *          {@code checkPermission} method denies enabling
   268      *          subclassing.
   268      *          subclassing.
   269      * @throws  IOException if an I/O error occurs while creating this stream
   269      * @throws  IOException if an I/O error occurs while creating this stream
   270      * @see SecurityManager#checkPermission
   270      * @see SecurityManager#checkPermission
   271      * @see java.io.SerializablePermission
   271      * @see java.io.SerializablePermission
   272      */
   272      */
   355         }
   355         }
   356     }
   356     }
   357 
   357 
   358     /**
   358     /**
   359      * Method used by subclasses to override the default writeObject method.
   359      * Method used by subclasses to override the default writeObject method.
   360      * This method is called by trusted subclasses of ObjectInputStream that
   360      * This method is called by trusted subclasses of ObjectOutputStream that
   361      * constructed ObjectInputStream using the protected no-arg constructor.
   361      * constructed ObjectOutputStream using the protected no-arg constructor.
   362      * The subclass is expected to provide an override method with the modifier
   362      * The subclass is expected to provide an override method with the modifier
   363      * "final".
   363      * "final".
   364      *
   364      *
   365      * @param   obj object to be written to the underlying stream
   365      * @param   obj object to be written to the underlying stream
   366      * @throws  IOException if there are I/O errors while writing to the
   366      * @throws  IOException if there are I/O errors while writing to the
   427      * this stream.  This may only be called from the writeObject method of the
   427      * this stream.  This may only be called from the writeObject method of the
   428      * class being serialized. It will throw the NotActiveException if it is
   428      * class being serialized. It will throw the NotActiveException if it is
   429      * called otherwise.
   429      * called otherwise.
   430      *
   430      *
   431      * @throws  IOException if I/O errors occur while writing to the underlying
   431      * @throws  IOException if I/O errors occur while writing to the underlying
   432      *          <code>OutputStream</code>
   432      *          {@code OutputStream}
   433      */
   433      */
   434     public void defaultWriteObject() throws IOException {
   434     public void defaultWriteObject() throws IOException {
   435         SerialCallbackContext ctx = curContext;
   435         SerialCallbackContext ctx = curContext;
   436         if (ctx == null) {
   436         if (ctx == null) {
   437             throw new NotActiveException("not in call to writeObject");
   437             throw new NotActiveException("not in call to writeObject");
   527      * Subclasses may implement this method to store custom data in the stream
   527      * Subclasses may implement this method to store custom data in the stream
   528      * along with descriptors for dynamic proxy classes.
   528      * along with descriptors for dynamic proxy classes.
   529      *
   529      *
   530      * <p>This method is called exactly once for each unique proxy class
   530      * <p>This method is called exactly once for each unique proxy class
   531      * descriptor in the stream.  The default implementation of this method in
   531      * descriptor in the stream.  The default implementation of this method in
   532      * <code>ObjectOutputStream</code> does nothing.
   532      * {@code ObjectOutputStream} does nothing.
   533      *
   533      *
   534      * <p>The corresponding method in <code>ObjectInputStream</code> is
   534      * <p>The corresponding method in {@code ObjectInputStream} is
   535      * <code>resolveProxyClass</code>.  For a given subclass of
   535      * {@code resolveProxyClass}.  For a given subclass of
   536      * <code>ObjectOutputStream</code> that overrides this method, the
   536      * {@code ObjectOutputStream} that overrides this method, the
   537      * <code>resolveProxyClass</code> method in the corresponding subclass of
   537      * {@code resolveProxyClass} method in the corresponding subclass of
   538      * <code>ObjectInputStream</code> must read any data or objects written by
   538      * {@code ObjectInputStream} must read any data or objects written by
   539      * <code>annotateProxyClass</code>.
   539      * {@code annotateProxyClass}.
   540      *
   540      *
   541      * @param   cl the proxy class to annotate custom data for
   541      * @param   cl the proxy class to annotate custom data for
   542      * @throws  IOException any exception thrown by the underlying
   542      * @throws  IOException any exception thrown by the underlying
   543      *          <code>OutputStream</code>
   543      *          {@code OutputStream}
   544      * @see ObjectInputStream#resolveProxyClass(String[])
   544      * @see ObjectInputStream#resolveProxyClass(String[])
   545      * @since   1.3
   545      * @since   1.3
   546      */
   546      */
   547     protected void annotateProxyClass(Class<?> cl) throws IOException {
   547     protected void annotateProxyClass(Class<?> cl) throws IOException {
   548     }
   548     }
   644      * Write the specified class descriptor to the ObjectOutputStream.  Class
   644      * Write the specified class descriptor to the ObjectOutputStream.  Class
   645      * descriptors are used to identify the classes of objects written to the
   645      * descriptors are used to identify the classes of objects written to the
   646      * stream.  Subclasses of ObjectOutputStream may override this method to
   646      * stream.  Subclasses of ObjectOutputStream may override this method to
   647      * customize the way in which class descriptors are written to the
   647      * customize the way in which class descriptors are written to the
   648      * serialization stream.  The corresponding method in ObjectInputStream,
   648      * serialization stream.  The corresponding method in ObjectInputStream,
   649      * <code>readClassDescriptor</code>, should then be overridden to
   649      * {@code readClassDescriptor}, should then be overridden to
   650      * reconstitute the class descriptor from its custom stream representation.
   650      * reconstitute the class descriptor from its custom stream representation.
   651      * By default, this method writes class descriptors according to the format
   651      * By default, this method writes class descriptors according to the format
   652      * defined in the Object Serialization specification.
   652      * defined in the Object Serialization specification.
   653      *
   653      *
   654      * <p>Note that this method will only be called if the ObjectOutputStream
   654      * <p>Note that this method will only be called if the ObjectOutputStream
   655      * is not using the old serialization stream format (set by calling
   655      * is not using the old serialization stream format (set by calling
   656      * ObjectOutputStream's <code>useProtocolVersion</code> method).  If this
   656      * ObjectOutputStream's {@code useProtocolVersion} method).  If this
   657      * serialization stream is using the old format
   657      * serialization stream is using the old format
   658      * (<code>PROTOCOL_VERSION_1</code>), the class descriptor will be written
   658      * ({@code PROTOCOL_VERSION_1}), the class descriptor will be written
   659      * internally in a manner that cannot be overridden or customized.
   659      * internally in a manner that cannot be overridden or customized.
   660      *
   660      *
   661      * @param   desc class descriptor to write to the stream
   661      * @param   desc class descriptor to write to the stream
   662      * @throws  IOException If an I/O error has occurred.
   662      * @throws  IOException If an I/O error has occurred.
   663      * @see java.io.ObjectInputStream#readClassDescriptor()
   663      * @see java.io.ObjectInputStream#readClassDescriptor()
   877      * to ObjectOutput.
   877      * to ObjectOutput.
   878      *
   878      *
   879      * @since 1.2
   879      * @since 1.2
   880      */
   880      */
   881     public abstract static class PutField {
   881     public abstract static class PutField {
       
   882         /**
       
   883          * Constructor for subclasses to call.
       
   884          */
       
   885         public PutField() {}
   882 
   886 
   883         /**
   887         /**
   884          * Put the value of the named boolean field into the persistent field.
   888          * Put the value of the named boolean field into the persistent field.
   885          *
   889          *
   886          * @param  name the name of the serializable field
   890          * @param  name the name of the serializable field
   887          * @param  val the value to assign to the field
   891          * @param  val the value to assign to the field
   888          * @throws IllegalArgumentException if <code>name</code> does not
   892          * @throws IllegalArgumentException if {@code name} does not
   889          * match the name of a serializable field for the class whose fields
   893          * match the name of a serializable field for the class whose fields
   890          * are being written, or if the type of the named field is not
   894          * are being written, or if the type of the named field is not
   891          * <code>boolean</code>
   895          * {@code boolean}
   892          */
   896          */
   893         public abstract void put(String name, boolean val);
   897         public abstract void put(String name, boolean val);
   894 
   898 
   895         /**
   899         /**
   896          * Put the value of the named byte field into the persistent field.
   900          * Put the value of the named byte field into the persistent field.
   897          *
   901          *
   898          * @param  name the name of the serializable field
   902          * @param  name the name of the serializable field
   899          * @param  val the value to assign to the field
   903          * @param  val the value to assign to the field
   900          * @throws IllegalArgumentException if <code>name</code> does not
   904          * @throws IllegalArgumentException if {@code name} does not
   901          * match the name of a serializable field for the class whose fields
   905          * match the name of a serializable field for the class whose fields
   902          * are being written, or if the type of the named field is not
   906          * are being written, or if the type of the named field is not
   903          * <code>byte</code>
   907          * {@code byte}
   904          */
   908          */
   905         public abstract void put(String name, byte val);
   909         public abstract void put(String name, byte val);
   906 
   910 
   907         /**
   911         /**
   908          * Put the value of the named char field into the persistent field.
   912          * Put the value of the named char field into the persistent field.
   909          *
   913          *
   910          * @param  name the name of the serializable field
   914          * @param  name the name of the serializable field
   911          * @param  val the value to assign to the field
   915          * @param  val the value to assign to the field
   912          * @throws IllegalArgumentException if <code>name</code> does not
   916          * @throws IllegalArgumentException if {@code name} does not
   913          * match the name of a serializable field for the class whose fields
   917          * match the name of a serializable field for the class whose fields
   914          * are being written, or if the type of the named field is not
   918          * are being written, or if the type of the named field is not
   915          * <code>char</code>
   919          * {@code char}
   916          */
   920          */
   917         public abstract void put(String name, char val);
   921         public abstract void put(String name, char val);
   918 
   922 
   919         /**
   923         /**
   920          * Put the value of the named short field into the persistent field.
   924          * Put the value of the named short field into the persistent field.
   921          *
   925          *
   922          * @param  name the name of the serializable field
   926          * @param  name the name of the serializable field
   923          * @param  val the value to assign to the field
   927          * @param  val the value to assign to the field
   924          * @throws IllegalArgumentException if <code>name</code> does not
   928          * @throws IllegalArgumentException if {@code name} does not
   925          * match the name of a serializable field for the class whose fields
   929          * match the name of a serializable field for the class whose fields
   926          * are being written, or if the type of the named field is not
   930          * are being written, or if the type of the named field is not
   927          * <code>short</code>
   931          * {@code short}
   928          */
   932          */
   929         public abstract void put(String name, short val);
   933         public abstract void put(String name, short val);
   930 
   934 
   931         /**
   935         /**
   932          * Put the value of the named int field into the persistent field.
   936          * Put the value of the named int field into the persistent field.
   933          *
   937          *
   934          * @param  name the name of the serializable field
   938          * @param  name the name of the serializable field
   935          * @param  val the value to assign to the field
   939          * @param  val the value to assign to the field
   936          * @throws IllegalArgumentException if <code>name</code> does not
   940          * @throws IllegalArgumentException if {@code name} does not
   937          * match the name of a serializable field for the class whose fields
   941          * match the name of a serializable field for the class whose fields
   938          * are being written, or if the type of the named field is not
   942          * are being written, or if the type of the named field is not
   939          * <code>int</code>
   943          * {@code int}
   940          */
   944          */
   941         public abstract void put(String name, int val);
   945         public abstract void put(String name, int val);
   942 
   946 
   943         /**
   947         /**
   944          * Put the value of the named long field into the persistent field.
   948          * Put the value of the named long field into the persistent field.
   945          *
   949          *
   946          * @param  name the name of the serializable field
   950          * @param  name the name of the serializable field
   947          * @param  val the value to assign to the field
   951          * @param  val the value to assign to the field
   948          * @throws IllegalArgumentException if <code>name</code> does not
   952          * @throws IllegalArgumentException if {@code name} does not
   949          * match the name of a serializable field for the class whose fields
   953          * match the name of a serializable field for the class whose fields
   950          * are being written, or if the type of the named field is not
   954          * are being written, or if the type of the named field is not
   951          * <code>long</code>
   955          * {@code long}
   952          */
   956          */
   953         public abstract void put(String name, long val);
   957         public abstract void put(String name, long val);
   954 
   958 
   955         /**
   959         /**
   956          * Put the value of the named float field into the persistent field.
   960          * Put the value of the named float field into the persistent field.
   957          *
   961          *
   958          * @param  name the name of the serializable field
   962          * @param  name the name of the serializable field
   959          * @param  val the value to assign to the field
   963          * @param  val the value to assign to the field
   960          * @throws IllegalArgumentException if <code>name</code> does not
   964          * @throws IllegalArgumentException if {@code name} does not
   961          * match the name of a serializable field for the class whose fields
   965          * match the name of a serializable field for the class whose fields
   962          * are being written, or if the type of the named field is not
   966          * are being written, or if the type of the named field is not
   963          * <code>float</code>
   967          * {@code float}
   964          */
   968          */
   965         public abstract void put(String name, float val);
   969         public abstract void put(String name, float val);
   966 
   970 
   967         /**
   971         /**
   968          * Put the value of the named double field into the persistent field.
   972          * Put the value of the named double field into the persistent field.
   969          *
   973          *
   970          * @param  name the name of the serializable field
   974          * @param  name the name of the serializable field
   971          * @param  val the value to assign to the field
   975          * @param  val the value to assign to the field
   972          * @throws IllegalArgumentException if <code>name</code> does not
   976          * @throws IllegalArgumentException if {@code name} does not
   973          * match the name of a serializable field for the class whose fields
   977          * match the name of a serializable field for the class whose fields
   974          * are being written, or if the type of the named field is not
   978          * are being written, or if the type of the named field is not
   975          * <code>double</code>
   979          * {@code double}
   976          */
   980          */
   977         public abstract void put(String name, double val);
   981         public abstract void put(String name, double val);
   978 
   982 
   979         /**
   983         /**
   980          * Put the value of the named Object field into the persistent field.
   984          * Put the value of the named Object field into the persistent field.
   981          *
   985          *
   982          * @param  name the name of the serializable field
   986          * @param  name the name of the serializable field
   983          * @param  val the value to assign to the field
   987          * @param  val the value to assign to the field
   984          *         (which may be <code>null</code>)
   988          *         (which may be {@code null})
   985          * @throws IllegalArgumentException if <code>name</code> does not
   989          * @throws IllegalArgumentException if {@code name} does not
   986          * match the name of a serializable field for the class whose fields
   990          * match the name of a serializable field for the class whose fields
   987          * are being written, or if the type of the named field is not a
   991          * are being written, or if the type of the named field is not a
   988          * reference type
   992          * reference type
   989          */
   993          */
   990         public abstract void put(String name, Object val);
   994         public abstract void put(String name, Object val);
   991 
   995 
   992         /**
   996         /**
   993          * Write the data and fields to the specified ObjectOutput stream,
   997          * Write the data and fields to the specified ObjectOutput stream,
   994          * which must be the same stream that produced this
   998          * which must be the same stream that produced this
   995          * <code>PutField</code> object.
   999          * {@code PutField} object.
   996          *
  1000          *
   997          * @param  out the stream to write the data and fields to
  1001          * @param  out the stream to write the data and fields to
   998          * @throws IOException if I/O errors occur while writing to the
  1002          * @throws IOException if I/O errors occur while writing to the
   999          *         underlying stream
  1003          *         underlying stream
  1000          * @throws IllegalArgumentException if the specified stream is not
  1004          * @throws IllegalArgumentException if the specified stream is not
  1001          *         the same stream that produced this <code>PutField</code>
  1005          *         the same stream that produced this {@code PutField}
  1002          *         object
  1006          *         object
  1003          * @deprecated This method does not write the values contained by this
  1007          * @deprecated This method does not write the values contained by this
  1004          *         <code>PutField</code> object in a proper format, and may
  1008          *         {@code PutField} object in a proper format, and may
  1005          *         result in corruption of the serialization stream.  The
  1009          *         result in corruption of the serialization stream.  The
  1006          *         correct way to write <code>PutField</code> data is by
  1010          *         correct way to write {@code PutField} data is by
  1007          *         calling the {@link java.io.ObjectOutputStream#writeFields()}
  1011          *         calling the {@link java.io.ObjectOutputStream#writeFields()}
  1008          *         method.
  1012          *         method.
  1009          */
  1013          */
  1010         @Deprecated
  1014         @Deprecated
  1011         public abstract void write(ObjectOutput out) throws IOException;
  1015         public abstract void write(ObjectOutput out) throws IOException;
  1586             bout.setBlockDataMode(oldMode);
  1590             bout.setBlockDataMode(oldMode);
  1587         }
  1591         }
  1588     }
  1592     }
  1589 
  1593 
  1590     /**
  1594     /**
  1591      * Converts specified span of float values into byte values.
       
  1592      */
       
  1593     // REMIND: remove once hotspot inlines Float.floatToIntBits
       
  1594     private static native void floatsToBytes(float[] src, int srcpos,
       
  1595                                              byte[] dst, int dstpos,
       
  1596                                              int nfloats);
       
  1597 
       
  1598     /**
       
  1599      * Converts specified span of double values into byte values.
       
  1600      */
       
  1601     // REMIND: remove once hotspot inlines Double.doubleToLongBits
       
  1602     private static native void doublesToBytes(double[] src, int srcpos,
       
  1603                                               byte[] dst, int dstpos,
       
  1604                                               int ndoubles);
       
  1605 
       
  1606     /**
       
  1607      * Default PutField implementation.
  1595      * Default PutField implementation.
  1608      */
  1596      */
  1609     private class PutFieldImpl extends PutField {
  1597     private class PutFieldImpl extends PutField {
  1610 
  1598 
  1611         /** class descriptor describing serializable fields */
  1599         /** class descriptor describing serializable fields */
  2090             int limit = MAX_BLOCK_SIZE - 4;
  2078             int limit = MAX_BLOCK_SIZE - 4;
  2091             int endoff = off + len;
  2079             int endoff = off + len;
  2092             while (off < endoff) {
  2080             while (off < endoff) {
  2093                 if (pos <= limit) {
  2081                 if (pos <= limit) {
  2094                     int avail = (MAX_BLOCK_SIZE - pos) >> 2;
  2082                     int avail = (MAX_BLOCK_SIZE - pos) >> 2;
  2095                     int chunklen = Math.min(endoff - off, avail);
  2083                     int stop = Math.min(endoff, off + avail);
  2096                     floatsToBytes(v, off, buf, pos, chunklen);
  2084                     while (off < stop) {
  2097                     off += chunklen;
  2085                         Bits.putFloat(buf, pos, v[off++]);
  2098                     pos += chunklen << 2;
  2086                         pos += 4;
       
  2087                     }
  2099                 } else {
  2088                 } else {
  2100                     dout.writeFloat(v[off++]);
  2089                     dout.writeFloat(v[off++]);
  2101                 }
  2090                 }
  2102             }
  2091             }
  2103         }
  2092         }
  2123             int limit = MAX_BLOCK_SIZE - 8;
  2112             int limit = MAX_BLOCK_SIZE - 8;
  2124             int endoff = off + len;
  2113             int endoff = off + len;
  2125             while (off < endoff) {
  2114             while (off < endoff) {
  2126                 if (pos <= limit) {
  2115                 if (pos <= limit) {
  2127                     int avail = (MAX_BLOCK_SIZE - pos) >> 3;
  2116                     int avail = (MAX_BLOCK_SIZE - pos) >> 3;
  2128                     int chunklen = Math.min(endoff - off, avail);
  2117                     int stop = Math.min(endoff, off + avail);
  2129                     doublesToBytes(v, off, buf, pos, chunklen);
  2118                     while (off < stop) {
  2130                     off += chunklen;
  2119                         Bits.putDouble(buf, pos, v[off++]);
  2131                     pos += chunklen << 3;
  2120                         pos += 8;
       
  2121                     }
  2132                 } else {
  2122                 } else {
  2133                     dout.writeDouble(v[off++]);
  2123                     dout.writeDouble(v[off++]);
  2134                 }
  2124                 }
  2135             }
  2125             }
  2136         }
  2126         }