@SuppressWarnings("serial")
class Person implements Serializable {
private String name; private int age; private transient String pwd; // transient 不序列化
// 構造器、getter/setter、toString
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
// 可加密敏感字段再寫入
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
// 解密還原
}
}
public class JdkSerialDemo {
public static void main(String[] args) throws Exception {
Person p = new Person("Jim", 28, "secret123");
// 序列化到文件
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.ser"))) {
oos.writeObject(p);
}
// 反序列化
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.ser"))) {
Person p1 = (Person) ois.readObject();
System.out.println(p1); // pwd 為 null (transient)
}
}
}
InvalidClassException。writeObject/readObject、writeReplace/readResolve(單例保護)、Externalizable 完全手動控制。ObjectInputFilter (JDK 9+) 白名單過濾。人類可讀、跨語言、版本兼容性好,適合配置文件、對外接口、日誌審計。
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.20</version>
</dependency>
public class XStreamDemo {
public static void main(String[] args) throws Exception {
// 1. 配置安全框架 (防 CVE-2021-21347 等)
XStream xs = new XStream(new DomDriver());
xs.allowTypes(new Class[]{RoadInfo.class, TableList.class}); // 白名單
// xs.allowTypesByWildcard(new String[]{"com.myapp.**"}); // 通配符
// 2. 別名簡化 XML
xs.alias("road", RoadInfo.class);
xs.alias("roads", TableList.class);
// 3. 反序列化 XML 文件
String xml = Files.readString(Path.of("roads.xml"));
TableList list = (TableList) xs.fromXML(xml);
System.out.println(list);
}
}
@XStreamAlias("road")
class RoadInfo { int id; long mdn; String name; double lng, lat; String icon; }
@XStreamAlias("roads")
class TableList { List<RoadInfo> roads = new ArrayList<>(); }
allowTypes,禁止反序列化任意類。@XStreamAlias、@XStreamAsAttribute、@XStreamImplicit 控制結構。xs.registerConverter(new JodaDateTimeConverter())。ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
String json = mapper.writeValueAsString(obj);
User u = mapper.readValue(json, User.class);
優勢:體積小、速度快、生態完善、支持流式處理、Spring Boot 默認集成。
| 場景 | 推薦方案 | 理由 |
|---|---|---|
| Java 內部 RPC、Session 複製 | Kryo / FST / Protobuf | 極致性能、體積小、支持循環引用 |
| 異構系統接口、配置文件、審計日誌 | JSON (Jackson) | 通用、可讀、工具鏈豐富 |
| 老系統對接、需 XML 格式 | XStream (白名單) | XML 標準、注解驅動 |
| 簡單對象持久化、教學演示 | JDK Serializable (UID) | 零依賴、語言內建 |
序列化看似簡單,實則暗藏版本兼容、安全漏洞、性能陷阱。原則:**首選 JSON/Protobuf,慎用 JDK 原生,禁用不可信反序列化,顯式 serialVersionUID,敏感字段 transient 加密**。