Skip to content

[아이템 90] 직렬화된 인스턴스 대신 직렬화 프록시 사용을 검토하라 #92

@zziri

Description

@zziri

Serializable 구현 문제

  • Serializable을 구현하면 생성자 이외의 방법으로 인스턴스 생성 가능
  • 버그와 보안문제
    -> 직렬화 프록시 패턴

SerializableProxy 구현

public class Period implements Serializable {
    private final Date start;
    private final Date end;
    
    public Period(Date start, Date end) {
        this.start = new Date(start.getTime());
        this.end = new Date(end.getTime());
        
        if(this.start.compareTo(this.end) > 0) {
            throw new IllegalArgumentException(start + "가 " + end + "보다 늦다.");
        }
    }
    private static class SerializationProxy implements Serializable {
        private final Date start;
        private final Date end;

        public SerializationProxy(Period p) {
            this.start = p.start;
            this.end = p.end;
        }
    }
}

직렬화 프록시는 바깥 클래스와 완전히 같은 필드로 구성

Period.writeReplace

public class Period implements Serializable {
    private Object writeReplace() {
        return new SerializationProxy(this);
    }
}

직렬화시 호출
바깥 클래스(Period) 타입을 직렬화할 수 없음

Period.readObject

public class Period implements Serializable {
    private void readObject(ObjectInputStream stream) throws InvalidObjectException {
        throw new InvalidObjectException("프록시가 필요합니다.");
    }
}

역직렬화시 호출
Period를 직접 역직렬화할 수 없음

Period.SerializableProxy.readResolve

public class Period implements Serializable {
    private static class SerializationProxy implements Serializable {
        private Object readResolve() {
            return new Period(start, end);
        }
    }
}

직렬화 프록시를 통해서만 역직렬화 가능
생성자 혹은 정적 메서드를 통해서만 객체를 생성하므로 불변식이 깨질 위험이 낮음

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions