常见异常及处理方式
- InvalidClassException
- 异常原因:当反序列化运行时检测到某个类的定义与序列化时不一致时抛出。例如类的 serialVersionUID 不匹配、类不存在等。
- 处理方式:
- 确保类的 serialVersionUID 一致。如果类的结构发生变化且希望保持兼容性,可以手动指定 serialVersionUID。
- 如果类不存在,需要确保相关类在类路径中正确存在。
- 示例:
import java.io.*;
class TestClass implements Serializable {
private static final long serialVersionUID = 1L;
String data;
}
public class SerializationExample {
public static void main(String[] args) {
try {
// 序列化
TestClass obj = new TestClass();
obj.data = "Hello";
FileOutputStream fos = new FileOutputStream("test.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(obj);
oos.close();
fos.close();
// 模拟类定义变化,修改 serialVersionUID
// 然后进行反序列化
FileInputStream fis = new FileInputStream("test.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
TestClass deserializedObj = (TestClass) ois.readObject();
ois.close();
fis.close();
System.out.println(deserializedObj.data);
} catch (IOException | ClassNotFoundException e) {
if (e instanceof InvalidClassException) {
System.out.println("InvalidClassException caught: " + e.getMessage());
// 处理方式示例:修改 serialVersionUID 使其匹配
} else {
e.printStackTrace();
}
}
}
}
- StreamCorruptedException
- 异常原因:当反序列化流的格式不正确,或者流已被损坏时抛出。比如在序列化数据传输过程中数据被篡改等情况。
- 处理方式:
- 验证序列化数据的来源和完整性,例如使用校验和(checksum)机制。
- 确保序列化和反序列化过程的环境和代码逻辑一致。
- 示例:
import java.io.*;
class CorruptedClass implements Serializable {
String info;
}
public class CorruptionExample {
public static void main(String[] args) {
try {
// 序列化
CorruptedClass obj = new CorruptedClass();
obj.info = "Original data";
FileOutputStream fos = new FileOutputStream("corrupt.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(obj);
oos.close();
fos.close();
// 模拟流损坏,手动修改文件内容
// 然后进行反序列化
FileInputStream fis = new FileInputStream("corrupt.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
CorruptedClass deserializedObj = (CorruptedClass) ois.readObject();
ois.close();
fis.close();
System.out.println(deserializedObj.info);
} catch (IOException | ClassNotFoundException e) {
if (e instanceof StreamCorruptedException) {
System.out.println("StreamCorruptedException caught: " + e.getMessage());
// 处理方式示例:重新获取正确的序列化数据
} else {
e.printStackTrace();
}
}
}
}
- OptionalDataException
- 异常原因:当反序列化流中包含比预期更多的数据时抛出。这可能发生在序列化过程中意外写入了额外的数据。
- 处理方式:
- 检查序列化和反序列化代码,确保正确处理数据写入和读取。
- 如果可能,在反序列化之前验证流的内容长度。
- 示例:
import java.io.*;
class ExtraDataClass implements Serializable {
int value;
}
public class ExtraDataExample {
public static void main(String[] args) {
try {
// 序列化
ExtraDataClass obj = new ExtraDataClass();
obj.value = 10;
FileOutputStream fos = new FileOutputStream("extra.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(obj);
// 意外写入额外数据
oos.writeInt(20);
oos.close();
fos.close();
// 反序列化
FileInputStream fis = new FileInputStream("extra.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
ExtraDataClass deserializedObj = (ExtraDataClass) ois.readObject();
// 这里会抛出 OptionalDataException
ois.close();
fis.close();
System.out.println(deserializedObj.value);
} catch (IOException | ClassNotFoundException e) {
if (e instanceof OptionalDataException) {
System.out.println("OptionalDataException caught: " + e.getMessage());
// 处理方式示例:修正序列化代码,避免写入额外数据
} else {
e.printStackTrace();
}
}
}
}
- ClassNotFoundException
- 异常原因:当反序列化时找不到要反序列化的类时抛出。这通常是因为类不在当前的类路径中。
- 处理方式:
- 确保所需的类在类路径中。如果是在不同的模块或 JAR 包中,确保相关依赖已正确添加。
- 示例:
import java.io.*;
class MissingClass implements Serializable {
String name;
}
public class MissingClassExample {
public static void main(String[] args) {
try {
// 序列化
MissingClass obj = new MissingClass();
obj.name = "Some Name";
FileOutputStream fos = new FileOutputStream("missing.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(obj);
oos.close();
fos.close();
// 模拟类缺失,注释掉 MissingClass 类定义后进行反序列化
FileInputStream fis = new FileInputStream("missing.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
MissingClass deserializedObj = (MissingClass) ois.readObject();
ois.close();
fis.close();
System.out.println(deserializedObj.name);
} catch (IOException | ClassNotFoundException e) {
if (e instanceof ClassNotFoundException) {
System.out.println("ClassNotFoundException caught: " + e.getMessage());
// 处理方式示例:确保 MissingClass 类在类路径中
} else {
e.printStackTrace();
}
}
}
}