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教程。