模块  java.base
软件包  java.io

Class ObjectInputStream

  • 实现的所有接口
    CloseableDataInputObjectInputObjectStreamConstantsAutoCloseable

    public class ObjectInputStream
    extends InputStream
    implements ObjectInput, ObjectStreamConstants
    ObjectInputStream对先前使用ObjectOutputStream编写的原始数据和对象进行反序列化。

    警告:不受信任数据的反序列化本质上是危险的,应该避免。 应根据Secure Coding Guidelines for Java SE的“序列化和反序列化”部分仔细验证不受信任的数据。 Serialization Filtering描述了防御性使用串行过滤器的最佳实践。

    当与FileOutputStream和FileInputStream一起使用时,ObjectOutputStream和ObjectInputStream可以为对象图提供持久存储的应用程序。 ObjectInputStream用于恢复以前序列化的对象。 其他用途包括使用套接字流在主机之间传递对象,或者用于在远程通信系统中编组和解组参数和参数。

    ObjectInputStream确保从流创建的图中的所有对象的类型与Java虚拟机中存在的类相匹配。 使用标准机制根据需要加载类。

    只能从流中读取支持java.io.Serializable或java.io.Externalizable接口的对象。

    方法readObject用于从流中读取对象。 应该使用Java的安全转换来获得所需的类型。 在Java中,字符串和数组是对象,在序列化期间被视为对象。 读取时,需要将它们转换为预期的类型。

    可以使用DataInput上的适当方法从流中读取原始数据类型。

    对象的默认反序列化机制将每个字段的内容还原为值,并在写入时键入。 反序列化过程将忽略声明为transient或static的字段。 对其他对象的引用会导致必要时从流中读取这些对象。 使用参考共享机制正确恢复对象图。 在反序列化时始终会分配新对象,这会阻止覆盖现有对象。

    读取对象类似于运行新对象的构造函数。 为对象分配内存并初始化为零(NULL)。 对非序列化类调用no-arg构造函数,然后从最接近java.lang.object的可序列化类开始,从流中恢复可序列化类的字段,并以对象的最特定类结束。

    例如,从ObjectOutputStream中的示例所写的流中读取:

      FileInputStream fis = new FileInputStream("t.tmp");
          ObjectInputStream ois = new ObjectInputStream(fis);
    
          int i = ois.readInt();
          String today = (String) ois.readObject();
          Date date = (Date) ois.readObject();
    
          ois.close(); 

    类通过实现java.io.Serializable或java.io.Externalizable接口来控制它们的序列化方式。

    实现Serializable接口允许对象序列化来保存和恢复对象的整个状态,并允许类在写入流的时间和读取时间之间进行演变。 它会自动遍历对象之间的引用,保存和恢复整个图形。

    在序列化和反序列化过程中需要特殊处理的可序列化类应实现以下方法:

      private void writeObject(java.io.ObjectOutputStream stream)
         throws IOException;
     private void readObject(java.io.ObjectInputStream stream)
         throws IOException, ClassNotFoundException;
     private void readObjectNoData()
         throws ObjectStreamException; 

    readObject方法负责使用通过相应writeObject方法写入流的数据来读取和恢复其特定类的对象的状态。 该方法不需要关注属于其超类或子类的状态。 通过从ObjectInputStream读取各个字段的数据并对对象的相应字段进行分配来恢复状态。 DataInput支持读取原始数据类型。

    任何读取超出相应writeObject方法写入的自定义数据边界的对象数据的尝试都将导致使用eof字段值为true抛出OptionalDataException。 超出分配数据末尾的非对象读取将以它们指示流结束的相同方式反映数据的结束:逐字节读取将返回-1作为字节读取或读取的字节数,以及原语读取将抛出EOFExceptions。 如果没有相应的writeObject方法,则默认序列化数据的结尾标记分配数据的结束。

    从readExternal方法中发出的原始和对象读取调用的行为方式相同 - 如果流已经位于相应writeExternal方法写入的数据的末尾,则对象读取将抛出OptionalofExceptions,并将eof设置为true,逐字节读取将返回-1,原始读取将抛出EOFExceptions。 请注意,对于使用旧的ObjectStreamConstants.PROTOCOL_VERSION_1协议编写的流,此行为不适用,其中writeExternal方法写入的数据末尾未划分,因此无法检测到。

    readObjectNoData方法负责在序列化流未将给定类列为要反序列化的对象的超类的情况下初始化其特定类的对象的状态。 如果接收方使用与发送方不同版本的反序列化实例的类,并且接收方的版本扩展了未由发送方版本扩展的类,则可能发生这种情况。 如果序列化流已被篡改,也可能发生这种情况; 因此,尽管存在“恶意”或不完整的源流,readObjectNoData对于正确初始化反序列化对象非常有用。

    序列化不会读取或为未实现java.io.Serializable接口的任何对象的字段赋值。 不可序列化的对象的子类可以是可序列化的。 在这种情况下,非可序列化类必须具有no-arg构造函数以允许其字段被初始化。 在这种情况下,子类负责保存和恢复非可序列化类的状态。 通常情况下,该类的字段可以访问(公共,包或受保护),或者有get和set方法可用于恢复状态。

    在反序列化期间可以过滤流的内容。 如果filter is set上的ObjectInputStream的,所述ObjectInputFilter可以检查类,阵列的长度,在流,深度和数量从输入流消耗的字节的参考数是允许的,如果没有,可以终止反序列化。 process-wide filter可以配置被应用到每个ObjectInputStream除非使用替换setObjectInputFilter

    反序列化对象时发生的任何异常都将被ObjectInputStream捕获并中止读取过程。

    实现Externalizable接口允许对象完全控制对象的序列化表单的内容和格式。 调用Externalizable接口的方法writeExternal和readExternal来保存和恢复对象状态。 当由类实现时,他们可以使用ObjectOutput和ObjectInput的所有方法编写和读取自己的状态。 对象负责处理发生的任何版本控制。

    枚举常量的反序列化与普通的可序列化或可外部化的对象不同。 枚举常量的序列化形式仅由其名称组成; 不传输常量的字段值。 要反序列化枚举常量,ObjectInputStream从流中读取常量名称; 然后通过使用枚举常量的基类型和接收的常量名称作为参数调用静态方法Enum.valueOf(Class, String)获得反序列化的常量。 与其他可序列化或可外部化的对象一样,枚举常量可以作为随后出现在序列化流中的反向引用的目标。 无法自定义枚举常量反序列化的过程:在反序列化期间,将忽略由枚举类型定义的任何特定于类的readObject,readObjectNoData和readResolve方法。 同样,任何serialPersistentFields或serialVersionUID字段声明也会被忽略 - 所有枚举类型都有一个固定的serialVersionUID为0L。

    从以下版本开始:
    1.1
    另请参见:
    DataInputObjectOutputStreamSerializableObject Serialization Specification, Section 3, Object Input Classes
    • 构造方法详细信息

      • ObjectInputStream

        public ObjectInputStream​(InputStream in)
                          throws IOException
        创建一个从指定的InputStream读取的ObjectInputStream。 从流中读取序列化流头并进行验证。 此构造函数将阻塞,直到相应的ObjectOutputStream已写入并刷新标头。

        序列化过滤器初始化为值the process-wide filter

        如果安装了安全管理器,则此构造函数将在子类的构造函数直接或间接调用时检查“enableSubclassImplementation”SerializablePermission,该子类覆盖ObjectInputStream.readFields或ObjectInputStream.readUnshared方法。

        参数
        in - 要读取的输入流
        异常
        StreamCorruptedException - 如果流标头不正确
        IOException - 如果在读取流标题时发生I / O错误
        SecurityException - 如果不信任的子类非法覆盖安全敏感方法
        NullPointerException - 如果 innull
        另请参见:
        ObjectInputStream()readFields()ObjectOutputStream(OutputStream)
    • 方法详细信息

      • readObject

        public final Object readObject()
                                throws IOException,
                                       ClassNotFoundException
        从ObjectInputStream中读取一个对象。 读取对象的类,类的签名,以及类的非瞬态和非静态字段及其所有超类型的值。 可以使用writeObject和readObject方法覆盖类的默认反序列化。 这个对象引用的对象是可传递的,因此readObject可以重建完整的等效对象图。

        当根对象的所有字段及其引用的对象完全恢复时,它将完全恢复。 此时,对象验证回调基于其注册的优先级按顺序执行。 回调由对象(在readObject特殊方法中)注册,因为它们是单独还原的。

        当不是null ,为每个对象(常规或类)读取序列化过滤器以重建根对象。 有关详细信息,请参见setObjectInputFilter

        对于InputStream和不应反序列化的类的问题,会抛出异常。 所有异常对InputStream都是致命的,并使其处于不确定状态; 由调用者忽略或恢复流状态。

        Specified by:
        readObject ,界面 ObjectInput
        结果
        从流中读取的对象
        异常
        ClassNotFoundException - 找不到序列化对象的类。
        InvalidClassException - 序列化使用的类有问题。
        StreamCorruptedException - 流中的控制信息不一致。
        OptionalDataException - 在流中找到原始数据而不是对象。
        IOException - 任何常见的输入/输出相关异常。
      • readUnshared

        public Object readUnshared()
                            throws IOException,
                                   ClassNotFoundException
        从ObjectInputStream中读取“非共享”对象。 此方法与readObject相同,不同之处在于它阻止对readObject和readUnshared的后续调用返回对通过此调用获得的反序列化实例的其他引用。 特别:
        • 如果调用readUnshared来反序列化反向引用(先前已写入流的对象的流表示),则抛出ObjectStreamException。
        • 如果readUnshared成功返回,则后续尝试反序列化对readUnshared反序列化的流句柄的反向引用将导致抛出ObjectStreamException。
        通过readUnshared反序列化对象会使与返回对象关联的流句柄无效。 请注意,这本身并不总能保证readUnshared返回的引用是唯一的; 反序列化对象可以定义readResolve方法,该方法返回对其他方可见的对象,或者readUnshared可以返回可在流中的其他位置或通过外部方式获得的Class对象或枚举常量。 如果反序列化对象定义了一个readResolve方法,并且该方法的调用返回一个数组,那么readUnshared将返回该数组的浅层克隆; 这保证了返回的数组对象是唯一的,并且无法在ObjectInputStream上调用readObject或readUnshared时再次获取,即使已经操作了基础数据流。

        当不是null ,为每个对象(常规或类)读取序列化过滤器以重建根对象。 有关详细信息,请参见setObjectInputFilter

        覆盖此方法的ObjectInputStream子类只能在拥有“enableSubclassImplementation”SerializablePermission的安全上下文中构造; 在没有此权限的情况下实例化此类子类的任何尝试都将导致抛出SecurityException。

        结果
        对反序列化对象的引用
        异常
        ClassNotFoundException - 如果找不到要反序列化的对象的类
        StreamCorruptedException - 如果流中的控制信息不一致
        ObjectStreamException - 如果要反序列化的对象已经出现在流中
        OptionalDataException - 如果原始数据是下一个流
        IOException - 如果在反序列化期间发生I / O错误
        从以下版本开始:
        1.4
      • defaultReadObject

        public void defaultReadObject()
                               throws IOException,
                                      ClassNotFoundException
        从此流中读取当前类的非静态和非瞬态字段。 这可能只能从被反序列化的类的readObject方法调用。 如果以其他方式调用它,它将抛出NotActiveException。
        异常
        ClassNotFoundException - 如果找不到序列化对象的类。
        IOException - 如果发生I / O错误。
        NotActiveException - 如果流当前未读取对象。
      • registerValidation

        public void registerValidation​(ObjectInputValidation obj,
                                       int prio)
                                throws NotActiveException,
                                       InvalidObjectException
        在返回图形之前注册要验证的对象。 虽然类似于resolveObject,但在重构整个图之后会调用这些验证。 通常,readObject方法将使用流注册对象,以便在恢复所有对象时可以执行最后一组验证。
        参数
        obj - 接收验证回调的对象。
        prio - 控制回调的顺序;零是一个很好的默认值。 使用较高的数字可以较早回调,较低的数字可用于以后的回调。 在优先级内,回调按特定顺序处理。
        异常
        NotActiveException - 流当前未读取对象,因此注册回调无效。
        InvalidObjectException - 验证对象为null。
      • resolveClass

        protected <?> resolveClass​(ObjectStreamClass desc)
                                 throws IOException,
                                        ClassNotFoundException
        加载等效于指定流类描述的本地类。 子类可以实现此方法以允许从备用源获取类。

        ObjectOutputStream的相应方法是annotateClass 对于流中的每个唯一类,此方法仅调用一次。 此子方法可以通过子类实现,以使用备用加载机制,但必须返回对象。 返回后,如果该类不是数组类,则将其serialVersionUID与序列化类的serialVersionUID进行比较,如果不匹配,则反序列化失败并抛出InvalidClassException

        ObjectInputStream中此方法的默认实现返回调用的结果

          Class.forName(desc.getName(), false, loader) 
        其中loader是当前线程堆栈中的第一个类加载器(从当前执行的方法开始),既不是platform class loader也不是它的祖先; 否则, loader平台类加载器 如果在此调用结果ClassNotFoundException和传递的名称ObjectStreamClass实例的基本类型或void Java语言的关键字,那么表示基本类型或void对象将被退回(例如, ObjectStreamClass名为"int"会被解决为Integer.TYPE )。 否则, ClassNotFoundException将被抛给此方法的调用者。
        参数
        desc - 类 ObjectStreamClass的实例
        结果
        对应于 desc对象
        异常
        IOException - 任何常见的输入/输出异常。
        ClassNotFoundException - 如果找不到序列化对象的类。
      • resolveProxyClass

        protected <?> resolveProxyClass​(String[] interfaces)
                                      throws IOException,
                                             ClassNotFoundException
        返回实现代理类描述符中指定的接口的代理类; 子类可以实现此方法以从流中读取自定义数据以及动态代理类的描述符,从而允许它们为接口和代理类使用备用加载机制。

        对于流中的每个唯一代理类描述符,此方法只调用一次。

        ObjectOutputStream的对应方法是annotateProxyClass 对于给定的子类ObjectInputStream ,它覆盖该方法中, annotateProxyClass中的相应子类方法ObjectOutputStream必须写由该方法读取的任何数据或对象。

        ObjectInputStream中此方法的默认实现返回调用Proxy.getProxyClass的结果, Proxy.getProxyClass包含interfaces参数中指定的接口的对象列表。 每个接口名称i对象是通过调用返回的值

          Class.forName(i, false, loader) 
        其中loader是当前线程堆栈中的第一个类加载器(从当前执行的方法开始),既不是platform class loader也不是它的祖先; 否则, loader平台类加载器 除非任何已解析的接口都是非公共接口, loader相同值也是传递给Proxy.getProxyClass的类加载器; 如果存在非公共接口,则会传递它们的类加载器(如果遇到多个非公共接口类加载器,则抛出IllegalAccessError )。 如果Proxy.getProxyClass抛出IllegalArgumentException ,则resolveProxyClass将抛出包含ClassNotFoundExceptionIllegalArgumentException
        参数
        interfaces - 代理类描述符中反序列化的接口名称列表
        结果
        指定接口的代理类
        异常
        IOException - 底层 InputStream引发的任何异常
        ClassNotFoundException - 如果 ClassNotFoundException代理类或任何命名接口
        从以下版本开始:
        1.3
        另请参见:
        ObjectOutputStream.annotateProxyClass(Class)
      • resolveObject

        protected Object resolveObject​(Object obj)
                                throws IOException
        此方法将允许ObjectInputStream的受信任子类在反序列化期间将一个对象替换为另一个对象。 在调用enableResolveObject之前,将禁用替换对象。 enableResolveObject方法检查请求解析对象的流是否可信。 对可序列化对象的每个引用都传递给resolveObject。 为了确保不会无意中暴露对象的私有状态,只有受信任的流可以使用resolveObject。

        在读取对象之后但在从readObject返回之前调用此方法。 默认的resolveObject方法只返回相同的对象。

        当子类替换对象时,它必须确保替换对象与将存储引用的每个字段兼容。 类型不是字段或数组元素类型的子类的对象通过引发异常来中止序列化,并且不存储该对象。

        首次遇到每个对象时,只调用一次此方法。 对该对象的所有后续引用都将重定向到新对象。

        参数
        obj - 要替换的对象
        结果
        被替换的对象
        异常
        IOException - 任何常见的输入/输出异常。
      • enableResolveObject

        protected boolean enableResolveObject​(boolean enable)
                                       throws SecurityException
        使流能够替换从流中读取的对象。 启用后,将为每个反序列化的对象调用resolveObject(java.lang.Object)方法。

        如果当前未启用对象替换,并且enable为true,并且安装了安全管理器,则此方法首先使用SerializablePermission("enableSubstitution")权限调用安全管理器的checkPermission方法,以确保允许调用者启用流来替换对象从流中读取。

        参数
        enable - 如果允许对每个要反序列化的对象使用 resolveObjectenable true
        结果
        调用此方法之前的先前设置
        异常
        SecurityException - 如果存在安全管理器且其 checkPermission方法拒绝启用流来替换从流中读取的对象。
        另请参见:
        SecurityManager.checkPermission(java.security.Permission)SerializablePermission
      • readStreamHeader

        protected void readStreamHeader()
                                 throws IOException,
                                        StreamCorruptedException
        提供readStreamHeader方法以允许子类读取和验证自己的流标头。 它会读取并验证幻数和版本号。
        异常
        IOException - 如果从底层 InputStream读取时存在I / O错误
        StreamCorruptedException - 如果流中的控制信息不一致
      • readClassDescriptor

        protected ObjectStreamClass readClassDescriptor()
                                                 throws IOException,
                                                        ClassNotFoundException
        从序列化流中读取类描述符。 当ObjectInputStream期望类描述符作为序列化流中的下一个项时,将调用此方法。 ObjectInputStream的子类可以重写此方法以读取以非标准格式编写的类描述符(通过重写writeClassDescriptor方法的ObjectOutputStream的子类)。 默认情况下,此方法根据对象序列化规范中定义的格式读取类描述符。
        结果
        类描述符读取
        异常
        IOException - 如果发生I / O错误。
        ClassNotFoundException - 如果找不到类描述符表示中使用的序列化对象的类
        从以下版本开始:
        1.3
        另请参见:
        ObjectOutputStream.writeClassDescriptor(java.io.ObjectStreamClass)
      • read

        public int read()
                 throws IOException
        读取一个字节的数据。 如果没有可用的输入,此方法将阻止。
        Specified by:
        read在界面 ObjectInput
        Specified by:
        readInputStream
        结果
        读取的字节,如果到达流的末尾,则返回-1。
        异常
        IOException - 如果发生I / O错误。
      • read

        public int read​(byte[] buf,
                        int off,
                        int len)
                 throws IOException
        读入一个字节数组。 此方法将阻止,直到某些输入可用。 考虑使用java.io.DataInputStream.readFully来准确读取'length'字节。
        Specified by:
        read在接口 ObjectInput
        重写:
        readInputStream
        参数
        buf - 读取数据的缓冲区
        off - 目标阵列 buf的起始偏移量
        len - 读取的最大字节数
        结果
        读取的实际字节数,当到达流的末尾时返回-1。
        异常
        NullPointerException - 如果 bufnull
        IndexOutOfBoundsException - 如果 off为负数,则 len为负数,或 len为大于 buf.length - off
        IOException - 如果发生I / O错误。
        另请参见:
        DataInputStream.readFully(byte[],int,int)
      • readFully

        public void readFully​(byte[] buf,
                              int off,
                              int len)
                       throws IOException
        读取字节,阻塞直到读取所有字节。
        Specified by:
        readFully ,界面 DataInput
        参数
        buf - 读取数据的缓冲区
        off - 数据阵列 buf的起始偏移量
        len - 要读取的最大字节数
        异常
        NullPointerException - 如果 bufnull
        IndexOutOfBoundsException - 如果 off为负数,则 len为负数,或 len为大于 buf.length - off
        EOFException - 如果到达文件末尾。
        IOException - 如果发生其他I / O错误。
      • skipBytes

        public int skipBytes​(int len)
                      throws IOException
        跳过字节。
        Specified by:
        skipBytes在界面 DataInput
        参数
        len - 要跳过的字节数
        结果
        跳过的实际字节数。
        异常
        IOException - 如果发生I / O错误。
      • readLine

        @Deprecated
        public String readLine()
                        throws IOException
        Deprecated.
        This method does not properly convert bytes to characters. see DataInputStream for the details and alternatives.
        读取已被\ n,\ r,\ r \ n或EOF终止的行。
        Specified by:
        readLine在界面 DataInput
        结果
        该行的String副本。
        异常
        IOException - 如果从底层 InputStream读取时存在I / O错误
      • setObjectInputFilter

        public final void setObjectInputFilter​(ObjectInputFilter filter)
        设置流的序列化过滤器。 为流中的每个类和引用调用过滤器的checkInput方法。 过滤器可以检查任何或所有类,数组长度,引用数,图的深度和输入流的大小。 深度是嵌套的readObject调用的数量,从读取被反序列化的图形的根开始,并且当前对象被反序列化。 引用的数量是对象的累积数量和对已从流中读取的对象的引用,包括正在读取的当前对象。 仅当从流中读取对象而不是基元时才调用过滤器。

        如果过滤器返回Status.REJECTEDnull或抛出一个RuntimeException ,主动readObjectreadUnshared抛出InvalidClassException ,否则反序列化不间断地继续。

        序列化过滤器被初始化为值ObjectInputFilter.Config.getSerialFilterObjectInputStream被构造和只能进行一次设置为自定义过滤器。

        实现要求:
        当不是null ,过滤器在readObjectreadUnshared期间为流中的每个对象(常规或类)调用。 字符串被视为基元,不会调用过滤器。 调用过滤器:
        • 先前从流中反序列化的每个对象引用(类为null ,arrayLength为-1),
        • 每个常规类(类不是null ,arrayLength是-1),
        • 动态代理的每个接口和动态代理类本身(类不是null ,arrayLength是-1),
        • 每个数组都使用数组类型和数组长度进行过滤(类是数组类型,arrayLength是请求的长度),
        • 每个被其类' readResolve方法替换的对象使用替换对象的类进行过滤,如果不是null ,如果是数组,则为arrayLength,否则为-1,
        • 如果不是null ,则使用替换对象的类过滤每个被resolveObject替换的对象,如果是数组,则使用arrayLength,否则为-1。
        当调用checkInput方法时,它被赋予对当前类的访问权限,数组长度,已从流中读取的当前引用数,对嵌套调用的深度为readObjectreadUnshared ,以及依赖于实现的字节数。输入流。

        每次调用readObjectreadUnshared在读取对象之前将深度增加1,并在正常返回或异常返回之前减少1。 深度从1开始,每个嵌套对象增加,并在每个嵌套调用返回时递减。 流中的引用计数从1开始,并在读取对象之前增加。

        参数
        filter - 过滤器,可以为null
        异常
        SecurityException - 如果有安全管理器且未授予 SerializablePermission("serialFilter")
        IllegalStateException - 如果 current filter不是 null且不是过程范围的过滤器
        从以下版本开始:
        9