EnumSet
:反序列化使用 反序列化代理
private static class SerializationProxy <E extends Enum<E>>
implements java.io.Serializable
{
/**
* The element type of this enum set.
*
* @serial
*/
private final Class<E> elementType;
/**
* The elements contained in this enum set.
*
* @serial
*/
private final Enum<?>[] elements;
SerializationProxy(EnumSet<E> set) {
elementType = set.elementType;
elements = set.toArray(ZERO_LENGTH_ENUM_ARRAY);
}
// instead of cast to E, we should perhaps use elementType.cast()
// to avoid injection of forged stream, but it will slow the implementation
@SuppressWarnings("unchecked")
private Object readResolve() {
EnumSet<E> result = EnumSet.noneOf(elementType);
for (Enum<?> e : elements)
result.add((E)e);
return result;
}
private static final long serialVersionUID = 362491234563181265L;
}
Object writeReplace() {
return new SerializationProxy<>(this);
}
// readObject method for the serialization proxy pattern
// See Effective Java, Second Ed., Item 78.
private void readObject(java.io.ObjectInputStream stream)
throws java.io.InvalidObjectException {
throw new java.io.InvalidObjectException("Proxy required");
}
writeReplace
: 这个方法的存在就是导致系统产生一个 SerializationProxy
实例,代替外围类的实例。换句话说 writeReplace
方法在序列化之前,将外围类的实例转变成了它的序列化代理。
有了 writeReplace
方法之后,序列化系统永远不会产生外围类的序列化实例,但是攻击者有可能伪造企图违反该类约束条件的示例。为了防止此类攻击,只需要在外围类中添加如下 readObject
方法。