Module java.base
Package java.io

Class ObjectInputStream

java.lang.Object
java.io.InputStream
java.io.ObjectInputStream
所有已实现的接口:
Closeable, DataInput, ObjectInput, ObjectStreamConstants, AutoCloseable

public class ObjectInputStream extends InputStream implements ObjectInput, ObjectStreamConstants
ObjectInputStream用于反序列化之前使用ObjectOutputStream写入的原始数据和对象。

警告:反序列化不受信任的数据本质上是危险的,应该避免使用。不受信任的数据应该根据Java SE的“安全编码准则”部分中的“序列化和反序列化”进行仔细验证。序列化过滤描述了防御性使用序列化过滤器的最佳实践。

禁用反序列化攻击的关键是防止对任意类的实例进行反序列化,从而防止直接或间接执行它们的方法。ObjectInputFilter描述了如何使用过滤器,ObjectInputFilter.Config描述了如何配置过滤器和过滤器工厂。每个流都有一个可选的反序列化过滤器,用于在反序列化过程中检查类和资源限制。JVM范围的过滤器工厂确保可以在每个ObjectInputStream上设置过滤器,并且可以检查从流中读取的每个对象。ObjectInputStream构造函数调用过滤器工厂以选择初始过滤器,该过滤器可以通过setObjectInputFilter(java.io.ObjectInputFilter)进行更新或替换。

如果ObjectInputStream具有过滤器,则ObjectInputFilter可以检查流中允许的类、数组长度、流中的引用数量、深度和从输入流中消耗的字节数,如果不允许,则可以终止反序列化。

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

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

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

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

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

对象的默认反序列化机制将每个字段的内容恢复为写入时的值和类型。声明为transient或static的字段将被反序列化过程忽略。对其他对象的引用将导致必要时从流中读取这些对象。使用引用共享机制正确恢复对象图。在反序列化时总是分配新对象,这可以防止现有对象被覆盖。

读取对象类似于运行新对象的构造函数。为对象分配内存并将其初始化为零(NULL)。对于非可序列化类,将调用无参数构造函数,然后从流中恢复可序列化类的字段,从java.lang.object最接近的可序列化类开始,直到对象的最具体类结束。

例如,要从由ObjectOutputStream中的示例写入的流中读取:

    try (FileInputStream fis = new FileInputStream("t.tmp");
         ObjectInputStream ois = new ObjectInputStream(fis)) {
        String label = (String) ois.readObject();
        LocalDateTime dateTime = (LocalDateTime) ois.readObject();
        // 使用label和dateTime
    } catch (Exception ex) {
        // 处理异常
    }

类通过实现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方法写入的自定义数据边界的对象数据都将导致抛出OptionalDataException,eof字段值为true。超出分配数据结尾的非对象读取将反映数据的结束方式,就像它们指示流的结束一样:按字节读取将返回-1作为读取的字节或字节数,原始读取将抛出EOFExceptions。如果没有相应的writeObject方法,则默认序列化数据的结束标记将标记分配数据的结束。

从readExternal方法中发出的原始和对象读取调用行为相同--如果流已定位到由相应writeExternal方法写入的数据末尾,则对象读取将抛出eof设置为true的OptionalDataExceptions,按字节读取将返回-1,原始读取将抛出EOFExceptions。请注意,此行为不适用于使用旧的ObjectStreamConstants.PROTOCOL_VERSION_1协议编写的流,在该协议中,由writeExternal方法写入的数据的末尾没有被标记,因此无法检测到。

readObjectNoData方法负责在序列化流中不将给定类列为正在反序列化的对象的超类时,为该类的特定类初始化对象的状态。这可能发生在接收方使用与发送方不同版本的反序列化实例类的情况下,并且接收方的版本扩展了发送方版本未扩展的类。如果序列化流被篡改,则readObjectNoData对于正确初始化反序列化对象非常有用。

序列化不会读取或为未实现java.io.Serializable接口的任何对象的字段分配值。未序列化的对象的子类可以是可序列化的。在这种情况下,非可序列化类必须具有无参数构造函数,以允许初始化其字段。在这种情况下,子类有责任保存和恢复非可序列化类的状态。通常情况下,该类的字段是可访问的(public、package或protected),或者有可用于恢复状态的get和set方法。

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

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

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

记录的序列化方式与普通可序列化或可外部化对象不同。在反序列化期间,将调用记录的规范构造函数来构造记录对象。对于可序列化记录,将忽略某些与序列化相关的方法,例如readObject和writeObject。有关可序列化记录的更多信息,请参阅Java对象序列化规范,第1.13节“记录序列化”。

自从:
1.1
外部规范
参见:
  • Constructor Details

  • Method Details

    • readObject

      public final Object readObject() throws IOException, ClassNotFoundException
      从ObjectInputStream中读取一个对象。读取对象的类、类的签名以及类的非瞬态和非静态字段的值。可以使用writeObject和readObject方法覆盖类的默认反序列化。此对象引用的对象会被递归读取,以便通过readObject重建对象的完整等效图。

      当所有字段及其引用的对象完全恢复时,根对象将完全恢复。此时,根据其注册的优先级顺序执行对象验证回调。这些回调由对象(在readObject特殊方法中)在它们被逐个恢复时注册。

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

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

      指定者:
      readObject 在接口 ObjectInput
      返回值:
      从流中读取的对象
      抛出:
      ClassNotFoundException - 无法找到序列化对象的类。
      InvalidClassException - 反序列化时使用的类出现问题。
      StreamCorruptedException - 流中的控制信息不一致。
      OptionalDataException - 流中发现原始数据而不是对象。
      IOException - 任何常见的输入/输出相关异常。
    • readObjectOverride

      protected Object readObjectOverride() throws IOException, ClassNotFoundException
      该方法由ObjectInputStream的受信任子类调用,该子类使用受保护的无参数构造函数构造ObjectInputStream。预期子类提供一个带有修饰符"final"的重写方法。
      返回值:
      从流中读取的对象。
      抛出:
      ClassNotFoundException - 无法找到序列化对象的类定义。
      OptionalDataException - 流中发现原始数据而不是对象。
      IOException - 从底层流读取时发生I/O错误
      自从:
      1.2
      参见:
    • readUnshared

      public Object readUnshared() throws IOException, ClassNotFoundException
      从ObjectInputStream中读取一个"unshared"对象。此方法与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 - 如果流当前未读取对象。
    • readFields

      从流中读取持久字段,并按名称使其可用。
      返回值:
      表示正在反序列化的对象的持久字段的GetField对象
      抛出:
      ClassNotFoundException - 如果无法找到序列化对象的类。
      IOException - 如果发生I/O错误。
      NotActiveException - 如果流当前未读取对象。
      自从:
      1.2
    • registerValidation

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

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

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

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

          Class.forName(desc.getName(), false, loader)
      
      其中loader是当前线程堆栈上第一个类加载器(从当前执行方法开始),既不是平台类加载器也不是其祖先;否则,loader是平台类加载器。如果此调用导致ClassNotFoundException,并且传递的ObjectStreamClass实例的名称是原始类型或void的Java语言关键字,则将返回表示该原始类型或void的Class对象(例如,具有名称"int"的ObjectStreamClass将解析为Integer.TYPE)。否则,将ClassNotFoundException抛出给此方法的调用者。
      参数:
      desc - ObjectStreamClass类的实例
      返回值:
      desc对应的Class对象
      抛出:
      IOException - 任何常见的输入/输出异常。
      ClassNotFoundException - 如果无法找到序列化对象的类。
    • resolveProxyClass

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

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

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

      ObjectInputStream中此方法的默认实现返回使用interfaces参数中命名的接口的Class对象列表调用Proxy.getProxyClass的结果。每个接口名称iClass对象是通过调用返回的值

          Class.forName(i, false, loader)
      
      其中loader是当前线程堆栈上的第一个类加载器(从当前执行的方法开始),既不是平台类加载器也不是其祖先;否则,loader平台类加载器。除非解析的接口中有非公共接口,否则loader的这个相同值也是传递给Proxy.getProxyClass的类加载器;如果存在非公共接口,则传递它们的类加载器(如果遇到多个非公共接口类加载器,则会抛出IllegalAccessError)。如果Proxy.getProxyClass抛出IllegalArgumentExceptionresolveProxyClass将抛出包含IllegalArgumentExceptionClassNotFoundException
      参数:
      interfaces - 在代理类描述符中反序列化的接口名称列表
      返回:
      指定接口的代理类
      抛出:
      IOException - 由底层InputStream抛出的任何异常
      ClassNotFoundException - 如果找不到代理类或任何命名的接口
      自:
      1.3
      参见:
    • 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,并且已安装安全管理器,则此方法首先调用安全管理器的checkPermission方法,以SerializablePermission("enableSubstitution")权限确保调用者被允许启用流以替换从流中读取的对象。

      参数:
      enable - 为每个正在反序列化的对象启用resolveObject的使用
      返回:
      在调用此方法之前的先前设置
      抛出:
      SecurityException - 如果存在安全管理器且其checkPermission方法拒绝启用流以替换从流中读取的对象。
      参见:
    • 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
      参见:
    • read

      public int read() throws IOException
      读取一个字节的数据。如果没有可用的输入,此方法将阻塞。
      在接口中指定:
      read 在接口 ObjectInput
      在类中指定:
      read 在类 InputStream
      返回:
      读取的字节,如果达到流的末尾则为-1。
      抛出:
      IOException - 如果发生I/O错误。
    • read

      public int read(byte[] buf, int off, int len) throws IOException
      读取到字节数组中。此方法将阻塞,直到有一些输入可用。考虑使用java.io.DataInputStream.readFully来精确读取'length'字节。
      在接口中指定:
      read 在接口 ObjectInput
      在类中覆盖:
      read 在类 InputStream
      参数:
      buf - 读取数据的目标数组
      off - 目标数组buf中的起始偏移量
      len - 要读取的最大字节数
      返回:
      读入缓冲区的总字节数,如果没有更多数据因为已达到流的末尾,则为-1
      抛出:
      NullPointerException - 如果bufnull
      IndexOutOfBoundsException - 如果off为负,len为负,或len大于buf.length - off
      IOException - 如果发生I/O错误。
      参见:
    • available

      public int available() throws IOException
      返回可以读取而不阻塞的字节数。
      在接口中指定:
      available 在接口 ObjectInput
      在类中覆盖:
      available 在类 InputStream
      返回:
      可用字节数。
      抛出:
      IOException - 如果从底层InputStream读取时发生I/O错误
    • close

      public void close() throws IOException
      关闭此输入流并释放与流关联的任何系统资源。
      指定者:
      close 在接口 AutoCloseable
      指定者:
      close 在接口 Closeable
      指定者:
      close 在接口 ObjectInput
      覆盖:
      close 在类 InputStream
      抛出:
      IOException - 如果发生I/O错误。
    • readBoolean

      public boolean readBoolean() throws IOException
      读取一个布尔值。
      指定者:
      readBoolean 在接口 DataInput
      返回:
      读取的布尔值。
      抛出:
      EOFException - 如果到达文件末尾。
      IOException - 如果发生其他I/O错误。
    • readByte

      public byte readByte() throws IOException
      读取一个8位字节。
      指定者:
      readByte 在接口 DataInput
      返回:
      读取的8位字节。
      抛出:
      EOFException - 如果到达文件末尾。
      IOException - 如果发生其他I/O错误。
    • readUnsignedByte

      public int readUnsignedByte() throws IOException
      读取一个无符号的8位字节。
      指定者:
      readUnsignedByte 在接口 DataInput
      返回:
      读取的8位字节。
      抛出:
      EOFException - 如果到达文件末尾。
      IOException - 如果发生其他I/O错误。
    • readChar

      public char readChar() throws IOException
      读取一个16位字符。
      指定者:
      readChar 在接口 DataInput
      返回:
      读取的16位字符。
      抛出:
      EOFException - 如果到达文件末尾。
      IOException - 如果发生其他I/O错误。
    • readShort

      public short readShort() throws IOException
      读取一个16位短整型数。
      指定者:
      readShort 在接口 DataInput
      返回:
      读取的16位短整型数。
      抛出:
      EOFException - 如果到达文件末尾。
      IOException - 如果发生其他I/O错误。
    • readUnsignedShort

      public int readUnsignedShort() throws IOException
      读取一个无符号的16位短整型数。
      指定者:
      readUnsignedShort 在接口 DataInput
      返回:
      读取的16位短整型数。
      抛出:
      EOFException - 如果到达文件末尾。
      IOException - 如果发生其他I/O错误。
    • readInt

      public int readInt() throws IOException
      读取一个32位整型数。
      指定者:
      readInt 在接口 DataInput
      返回:
      读取的32位整数。
      抛出:
      EOFException - 如果到达文件末尾。
      IOException - 如果发生其他I/O错误。
    • readLong

      public long readLong() throws IOException
      读取一个64位长整型数。
      指定者:
      readLong 在接口 DataInput
      返回:
      读取的64位长整型数。
      抛出:
      EOFException - 如果到达文件末尾。
      IOException - 如果发生其他I/O错误。
    • readFloat

      public float readFloat() throws IOException
      读取一个32位浮点数。
      指定者:
      readFloat 在接口 DataInput
      返回:
      读取的32位浮点数。
      抛出:
      EOFException - 如果到达文件末尾。
      IOException - 如果发生其他I/O错误。
    • readDouble

      public double readDouble() throws IOException
      读取一个64位双精度浮点数。
      指定者:
      readDouble 在接口 DataInput
      返回:
      读取的64位双精度浮点数。
      抛出:
      EOFException - 如果到达文件末尾。
      IOException - 如果发生其他I/O错误。
    • readFully

      public void readFully(byte[] buf) throws IOException
      读取字节,阻塞直到所有字节都被读取。
      指定者:
      readFully 在接口 DataInput
      参数:
      buf - 读取数据的缓冲区
      抛出:
      NullPointerException - 如果bufnull
      EOFException - 如果到达文件末尾。
      IOException - 如果发生其他I/O错误。
    • readFully

      public void readFully(byte[] buf, int off, int len) throws IOException
      读取字节,阻塞直到所有字节都被读取。
      指定者:
      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
      跳过字节。
      指定者:
      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终止的行。
      指定者:
      readLine 在接口 DataInput
      返回:
      行的字符串副本。
      抛出:
      IOException - 如果从底层InputStream读取时发生I/O错误
    • readUTF

      public String readUTF() throws IOException
      读取以修改后的UTF-8格式的字符串。
      指定者:
      readUTF 在接口 DataInput
      返回:
      字符串。
      抛出:
      IOException - 如果从底层InputStream读取时发生I/O错误
      UTFDataFormatException - 如果读取的字节不表示字符串的有效修改后的UTF-8编码
    • getObjectInputFilter

      public final ObjectInputFilter getObjectInputFilter()
      返回此流的反序列化过滤器。过滤器是通过调用JVM范围的过滤器工厂的结果得到的,可以通过构造函数或最近一次调用setObjectInputFilter来设置。
      返回:
      流的反序列化过滤器;可能为null
      自:
      9
    • setObjectInputFilter

      public final void setObjectInputFilter(ObjectInputFilter filter)
      设置流的反序列化过滤器。反序列化过滤器设置为通过使用JVM范围的过滤器工厂当前过滤器以及filter参数调用返回的过滤器。当前过滤器是在ObjectInputStream构造函数中通过调用JVM范围的过滤器工厂设置的,可能为nullsetObjectInputFilter(ObjectInputFilter)此方法只能在从流中读取任何对象之前调用一次,并且只能调用一次;例如,通过调用readObject()readUnshared()

      不允许将非null过滤器替换为null过滤器。如果当前过滤器非null,则从过滤器工厂返回的值必须为非null

      过滤器的checkInput方法将针对流中的每个类和引用进行调用。过滤器可以检查类的任何或所有内容,数组长度,引用数量,图的深度以及输入流的大小。深度是从正在反序列化的图的根部开始读取并正在反序列化的当前对象开始的嵌套readObject调用的数量。引用数量是已从流中读取的对象和对象引用的累积数量,包括当前正在读取的对象。仅在从流中读取对象时才调用过滤器,而不是对基本类型。

      如果过滤器返回Status.REJECTEDnull或抛出RuntimeException,则活动的readObjectreadUnshared将抛出InvalidClassException,否则反序列化将继续无间断。

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

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

      参数:
      filter - 过滤器,可能为null
      抛出:
      SecurityException - 如果存在安全管理器且未授予SerializablePermission("serialFilter")
      IllegalStateException - 如果已读取对象,如果过滤器工厂在当前过滤器为非null时返回null,或者如果过滤器已经设置。
      自:
      9