본문 바로가기
프로그래밍 놀이터/디자인 패턴, 리펙토링

[Effective Java] 인스턴스 제어에는 readResolve 메소드보다 enum 타입을 사용하자.

by 돼지왕 왕돼지 2017. 3. 27.
반응형

 [Effective Java] 인스턴스 제어에는 readResolve 메소드보다 enum 타입을 사용하자.


classcastexception, deserialization, Effective JAVA, enum, enum 타입, Final, GC, instance, object, override, Private, Protected, Public, readobject, readresolve, Serialize, Singleton, transient, [Effective Java] 인스턴스 제어에는 readResolve 메소드보다 enum 타입을 사용하자., 객체 참조, 공격, 공격자, 기본형, 대체, 불변 규칙, 서브 클래스, 슈퍼 클래스, 슈퍼 클래스 인스턴스, 싱글톤, 역직렬화, 오버라이딩, 인스턴스, 인스턴스 제어, 접근성, 정의, 주의, 직렬화, 허술


-
readResolve 메소드는 readObject 메소드에서 생성한 인스턴스를 다른 인스턴스로 바꾸어준다.
만일 역직렬화되는 객체의 클래스에서 readResolve 메소드를 올바르게 정의하면
그 객체가 역직렬화된 후 그 결과로 새롭게 생성된 객체에 대해 이 메소드가 자동 호출되며, 이 메소드에서 반환하는 객체 참조가 역직렬화로 새롭게 생성된 객체 대신 반환된다.


-
싱글톤의 경우 다음과 같은 방법으로 싱글톤을 유지할 수 있다.

private Object readResolve(){

// Deserialization 으로 생성된 새로운 녀석은 GC 된다.

return INSTANCE;

}



-
readResolve 메소드에 의존해서 인스턴스 제어를 한다면,
객체 참조 타입을 갖는 모든 인스턴스 필드는 반드시 transient 로 선언해야 한다.
그렇게 하지 않으면, 침입을 작심한 공격자가 역직렬화된 객체의 readResolve 메소드가 실행되기 전에 그 객체 참조를 획득할 수 있다.


-
readResolve 와 transient 를 사용하여 singleton 의 serialize 를 해결할 수 있지만,
허술하고 많은 주의를 요한다.
가장 좋은 방법은 enum 으로 작성하면 된다는 것이다.

public enum Elvis{

INSTANCE;

....

}



-
readResolve 메소드의 접근성이 중요하다.
readResolve 메소드를 final 클래스에 둘 때는 반드시 private 이 되어야 한다.
final 이 아닌 클래스에 둘 때는 그 메소드의 접근성을 신중하게 고려해야 한다.
만일 readResolve 메소드가 protected 나 public 이면서 그 메소드를 서브 클래스가 오버라이딩 하지 않는다면, 직렬화된 서브 클래스 인스턴스를 역직렬화 할 때 ClassCastException 예외를 발생시킬 수 있는 수퍼 클래스 인스턴스를 생성한다.



Summary


인스턴스 제어에 관련된 불변 규칙이 있어서 그것을 지키게 해야 한다면 enum 타입을 사용해야 한다.
만일 enum 타입을 사용할 수 없고, 직렬화 가능하면서 인스턴스 제어도 해야 하는 클래스가 필요하다면,
그 클래스에 readResolve 메소드를 제공해야 한다.
그리고 그 클래스의 모든 인스턴스 필드가 기본형 타입이나 transient 중 하나가 되도록 해야 한다.





반응형

댓글