Java序列化:实例控制与序列化代理模式
立即解锁
发布时间: 2025-08-18 00:25:52 阅读量: 1 订阅数: 4 

### Java序列化:实例控制与序列化代理模式
#### 1. 实例控制:优先使用枚举类型而非 readResolve
在Java编程中,单例模式是一种常见的设计模式,用于确保一个类只有一个实例。以下是一个单例类的示例:
```java
public class Elvis {
public static final Elvis INSTANCE = new Elvis();
private Elvis() { ... }
public void leaveTheBuilding() { ... }
}
```
然而,如果在类的声明中添加 “implements Serializable”,这个类将不再是单例。因为任何 `readObject` 方法,无论是显式的还是默认的,都会返回一个新创建的实例,这与类初始化时创建的实例不同。
为了解决这个问题,可以使用 `readResolve` 特性。如果被反序列化对象的类定义了一个具有正确声明的 `readResolve` 方法,该方法将在新创建的对象反序列化后被调用,并且该方法返回的对象引用将替代新创建的对象。例如,如果 `Elvis` 类实现了 `Serializable`,可以添加以下 `readResolve` 方法来保证单例属性:
```java
// readResolve for instance control - you can do better!
private Object readResolve() {
// Return the one true Elvis and let the garbage collector
// take care of the Elvis impersonator.
return INSTANCE;
}
```
但是,如果单例类包含非瞬态对象引用字段,可能会受到攻击。攻击者可以在单例的 `readResolve` 方法运行之前获取对反序列化对象的引用。以下是一个具体的攻击示例:
```java
// Broken singleton - has nontransient object reference field!
public class Elvis implements Serializable {
public static final Elvis INSTANCE = new Elvis();
private Elvis() { }
private String[] favoriteSongs =
{ "Hound Dog", "Heartbreak Hotel" };
public void printFavorites() {
System.out.println(Arrays.toString(favoriteSongs));
}
private Object readResolve() throws ObjectStreamException {
return INSTANCE;
}
}
public class ElvisStealer implements Serializable {
static Elvis impersonator;
private Elvis payload;
private Object readResolve() {
// Save a reference to the "unresolved" Elvis instance
impersonator = payload;
// Return an object of correct type for favorites field
return new String[] { "A Fool Such as I" };
}
private static final long serialVersionUID = 0;
}
public class ElvisImpersonator {
// Byte stream could not have come from real Elvis instance!
private static final byte[] serializedForm = new byte[] {
(byte)0xac, (byte)0xed, 0x00, 0x05, 0x73, 0x72, 0x00, 0x05,
0x45, 0x6c, 0x76, 0x69, 0x73, (byte)0x84, (byte)0xe6,
(byte)0x93, 0x33, (byte)0xc3, (byte)0xf4, (byte)0x8b,
0x32, 0x02, 0x00, 0x01, 0x4c, 0x00, 0x0d, 0x66, 0x61, 0x76,
0x6f, 0x72, 0x69, 0x74, 0x65, 0x5
```
0
0
复制全文
相关推荐










