Java ObjectStreamException 类
最后修改时间:2025 年 4 月 16 日
java.io.ObjectStreamException
是所有特定于对象流类的异常的超类。 它指示对象序列化或反序列化期间出现的问题。 此异常扩展了 IOException
。
ObjectStreamException
有几个子类,代表特定的序列化问题。 这些包括 InvalidClassException
、NotSerializableException
和 StreamCorruptedException
。 每个子类处理不同的序列化失败场景。
ObjectStreamException 类概述
ObjectStreamException
是一个抽象类,用作对象流异常的基础。 它提供构造函数来创建带有详细消息的异常。 该类本身没有添加超出标准异常功能的新方法。
public abstract class ObjectStreamException extends IOException { protected ObjectStreamException(String classname); protected ObjectStreamException(); }
上面的代码显示了 ObjectStreamException
的基本结构。 它有两个构造函数 - 一个带有消息,一个没有。 具体子类为不同的序列化问题提供特定的异常类型。
InvalidClassException 示例
当序列化运行时检测到类存在问题时,会发生 InvalidClassException
。 这包括 serialVersionUID 不匹配或无效的类定义。 该异常提供了有关问题类的详细信息。
import java.io.*; class Data implements Serializable { private static final long serialVersionUID = 1L; private String info; // Changed class definition after serialization private int newField; // Added after initial serialization } public class Main { public static void main(String[] args) { try { // Serialize ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream("data.ser")); out.writeObject(new Data()); out.close(); // Modify class definition (change serialVersionUID) // Then attempt deserialization ObjectInputStream in = new ObjectInputStream( new FileInputStream("data.ser")); Data obj = (Data) in.readObject(); in.close(); } catch (InvalidClassException e) { System.err.println("InvalidClassException: " + e.getMessage()); e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } }
此示例演示了当类定义更改时如何发生 InvalidClassException
。 在序列化对象后,修改类(例如添加字段)可能会在反序列化期间导致此异常。 serialVersionUID 不匹配是一个常见原因。
NotSerializableException 示例
当对象未标记为 Serializable
时,会抛出 NotSerializableException
。 序列化图中的所有对象都必须实现 Serializable
。 此异常标识不可序列化的类。
import java.io.*; class NonSerializableData { private String info = "Cannot serialize me"; } class Container implements Serializable { private NonSerializableData data = new NonSerializableData(); } public class Main { public static void main(String[] args) { try { ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream("container.ser")); out.writeObject(new Container()); out.close(); } catch (NotSerializableException e) { System.err.println("NotSerializableException: " + e.getMessage()); e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
此示例显示了尝试序列化包含不可序列化字段的对象时的 NotSerializableException
。 Container
类是可序列化的,但其 NonSerializableData
字段不是。 该异常在其消息中标识了有问题类。
StreamCorruptedException 示例
StreamCorruptedException
指示流协议已被违反。 当流数据已损坏或被篡改时,会发生这种情况。 该异常表明流不是预期的格式。
import java.io.*; public class Main { public static void main(String[] args) { try { // Create a valid serialized file ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream("data.ser")); out.writeObject("Hello, Serialization!"); out.close(); // Corrupt the file by appending random data RandomAccessFile raf = new RandomAccessFile("data.ser", "rw"); raf.seek(raf.length()); raf.writeBytes("CORRUPTED DATA"); raf.close(); // Attempt to read corrupted file ObjectInputStream in = new ObjectInputStream( new FileInputStream("data.ser")); String obj = (String) in.readObject(); in.close(); } catch (StreamCorruptedException e) { System.err.println("StreamCorruptedException: " + e.getMessage()); e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } }
此示例故意损坏序列化文件以演示 StreamCorruptedException
。 在创建有效的序列化文件后,我们附加随机数据以损坏它。 尝试反序列化时,由于流格式无效,因此会发生异常。
OptionalDataException 示例
当发现原始数据而不是对象时,在反序列化期间会发生 OptionalDataException
。 这通常发生在读取使用自定义序列化方法编写的流时。 该异常指示意外的数据类型。
import java.io.*; class CustomData implements Serializable { private void writeObject(ObjectOutputStream out) throws IOException { out.writeInt(42); // Write primitive instead of object } } public class Main { public static void main(String[] args) { try { // Serialize ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream("custom.ser")); out.writeObject(new CustomData()); out.close(); // Deserialize ObjectInputStream in = new ObjectInputStream( new FileInputStream("custom.ser")); CustomData obj = (CustomData) in.readObject(); in.close(); } catch (OptionalDataException e) { System.err.println("OptionalDataException: " + e.getMessage()); System.out.println("Primitive data found: " + e.length + " bytes"); e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } }
此示例显示了自定义序列化写入原始数据时的 OptionalDataException
。 CustomData
类直接将整数写入流。 在反序列化期间,系统期望对象,但却找到原始数据。
WriteAbortedException 示例
当原始序列化失败时,在反序列化期间会发生 WriteAbortedException
。 它包装了导致写入中止的异常。 这提供了有关序列化失败原因的上下文。
import java.io.*; class ProblematicData implements Serializable { private Object nonSerializable = new Object(); } public class Main { public static void main(String[] args) { try { // Attempt serialization (will fail) ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(baos); out.writeObject(new ProblematicData()); out.close(); } catch (NotSerializableException e) { try { // Now attempt to deserialize the partial stream ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray()); ObjectInputStream in = new ObjectInputStream(bais); in.readObject(); in.close(); } catch (WriteAbortedException wae) { System.err.println("WriteAbortedException: " + wae.getMessage()); System.out.println("Original exception: " + wae.detail.getMessage()); wae.printStackTrace(); } catch (Exception ex) { ex.printStackTrace(); } } } }
此示例通过首先尝试序列化不可序列化的对象来演示 WriteAbortedException
。 序列化失败后,我们尝试反序列化部分流。 该异常包含有关导致中止的原始失败的详细信息。
InvalidObjectException 示例
当反序列化对象的验证失败时,会抛出 InvalidObjectException
。 这通常发生在 readObject
方法中的自定义验证期间。 它指示对象未通过后处理检查。
import java.io.*; class ValidatedData implements Serializable { private int value; private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); if (value < 0 || value > 100) { throw new InvalidObjectException("Value must be between 0 and 100"); } } } public class Main { public static void main(String[] args) { try { // Serialize valid data ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(baos); ValidatedData valid = new ValidatedData(); valid.value = 50; out.writeObject(valid); out.close(); // Modify serialized data to make it invalid byte[] data = baos.toByteArray(); // Corrupt the value to be 200 (simulating invalid data) data[data.length - 1] = (byte) 200; // Attempt deserialization ByteArrayInputStream bais = new ByteArrayInputStream(data); ObjectInputStream in = new ObjectInputStream(bais); ValidatedData obj = (ValidatedData) in.readObject(); in.close(); } catch (InvalidObjectException e) { System.err.println("InvalidObjectException: " + e.getMessage()); e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } }
此示例显示了自定义验证期间的 InvalidObjectException
。 ValidatedData
类检查其值是否在 0-100 范围内。 我们通过直接修改序列化的字节来模拟无效数据。 验证在反序列化期间失败。
来源
Java ObjectStreamException 类文档
在本文中,我们介绍了 ObjectStreamException
类及其常见的子类。 了解这些异常对于 Java 应用程序中健壮的对象序列化和反序列化至关重要。
作者
列出所有Java教程。