NMP-Study / EffectiveJava2022

Effective Java Study 2022
5 stars 0 forks source link

아이템 89. 인스턴스 수를 통제해야 한다면 readResolve보다는 열거 타입을 사용하라 #89

Closed okhee closed 1 year ago

luckyDaveKim commented 1 year ago

Serializable를 구현하는 순간, 더 이상 싱글턴이 아니다.

readResolve를 사용하면, readObject가 만들어낸 인스턴스를 다른것으로 대체할 수 있다. 이때 readObject가 만들어낸 인스턴스는 gc대상이 된다.

public class Elvis implements Serializable {
    public static final Elvis INSTANCE = new Elvis();

    private Elvis() {}

    private String[] favoriteSongs = {"REAL"};

    public void printFavorites() {
        System.out.println(Arrays.toString(favoriteSongs));
    }

    private Object readResolve() {
        return INSTANCE;
    }
}

만약, readResolve를 인스턴스 통제 목적으로 이용한다면, 모든 필드를 transient로 선언해야 한다. 그렇지 않으면 readResolve 메서드가 수행되기 전에 역질렬화된 객체의 참조를 공격할 여지가 남는다.

필드를 transient 로 선언하여 위와 같은 공격을 피할 수 있다. 하지만, Elvis를 원소 하나짜리 enum 타입으로 바꾸면 위 과정들을 고민하지 않아도 된다. (하지만 reflection을 사용하면 모든 방어가 무력화된다)

결론