Java ‐ 인스턴스 수를 통제해야 한다면 readResolve보다는 열거 타입을 사용하라[Effective Java Item 89] - thought-corner/Backend-PlayGround GitHub Wiki

싱글톤을 직렬화하는 경우 문제점

  • 싱글톤으로 구현된 클래스는 인스턴스가 하나만 생성됨을 보장할 수 있다.
  • 클래스에 implements Serializable로 인터페이스를 구현한다면 더 이상 싱글톤이 아니게 된다.
  • 인터페이스를 구현하면 기본 직렬화를 쓰지 않더라도, 그리고 명시적인 readObject를 제공하더라도 소용없다.
  • 어떤 readObject를 사용하든 이 클래스가 초기화될 때 만들어진 인스턴스와는 별개의 인스턴스가 반환된다.

readResolve() 기능을 사용하는 경우

  • readObject()가 만들어낸 인스턴스를 다른 것으로 대체할 수 있다.
  • 역직렬화된 객체의 클래스가 readResolve() 메서드를 적절히 정의했다면 역직렬화 후 새로 생성된 객체를 인수로 이 메서드가 호출한다.
  • 이 메서드가 반환한 객체 참조가 새로 생성된 객체를 대신해 반환된다.
  • 대부분의 경우 이 때 새로 생성된 객체 참조는 유지되지 않으므로 바로 GC의 대상이 된다.

Serializable 구현과 readResolve() 메서드 제공

  • 싱글턴 속성을 유지하기 위한 방법
    • readResolve() : 역직렬화된 객체를 무시하고 클래스 초기화 때 만들어진 인스턴스를 반환. 이 때, 인스턴스의 직렬화 형탠은 아무런 실 데이터를 가질 이유가 없기에 모든 인스턴스 필드를 transient로 선언한다.
    • readResolve()를 인스턴스 통제 목적으로 사용하려는 경우 : 객체 참조 타입 인스턴스 필드는 모두 transient로 선언해야 한다. 조건이 충족되지 않으면 readResolve() 메서드가 수행되기 전에 역직렬화된 객체의 참조를 공격할 여지가 남게 된다.