티스토리 뷰
싱글턴과 직렬화
public class Elvis {
public static final Elvis INSTANCE = new Elvis();
private Elvis() { ... }
public void leaveTheBuild丄ng() { ... }
}
- Serializable 을 추가하는 순간 더 이상 싱글턴이 아니게 된다
- 어떤 readObject()를 사용하든 이 클래스가 초기화될 때 만들어진 인스턴스와는 별개인 인스턴스를 반환한다.
- readResolve()를 사용하면 readObject()가 만들어낸 인스턴스를 다른 것으로 대체할 수 있다. 역직렬화된 새 인스턴스는 참조를 잃어 자동적으로 GC 대상이 된다.
private Object readResolve() {
return INSTANCE;
}
해당 싱글턴 인스턴스의 직렬화 형태는 실 데이터를 가질 이유가 없으므로, 모든 인스턴스 필드를 transient로 선언해야 한다.
- 즉,
readResolve()
를 인스턴스 통제 목적으로 사용한다면 객체 참조 타입 인스턴스 필드를 모두 transient로 선언하자.
- 즉,
그렇지 않으면 역직렬화된 객체의 참조를 공격할 여지가 남는다.
싱글턴이 transient가 아닌 참조 필드를 가지고 있다면, 필드의 내용은
readResolve()
실행 전에 역직렬화된다.잘 조작된 스트림을 사용하면 해당 필드의 내용이 역직렬화되는 시점에 해당 역직렬화된 인스턴스의 참조를 훔쳐올 수 있다.
readResolve() 메서드를 사용해 순간적으로 만들어진 역직렬화된 인스턴스에 접근하지 못하게 하는 방법은 깨지기 쉽고 신경을 쓰기 어렵다. 싱글턴의 모든 인스턴스 필드에 transient를 붙이면 해결되지만, 열거 타입을 사용하는 것이 더 낫다
열거형과 직렬화
public enum Elvis { INSTANCE; private String[] favoriteSongs = { "Hound Dog", "Heartbreak Hotel" }; public void printFavorites() { System.out.println(Arrays.toString(favoriteSongs)); } }
직렬화 가능한 인스턴스 통제 클래스를 열거 타입으로 구현한다면 선언 상수 외의 다른 객체는 존재하지 않음을 Java가 보장한다.
- 네이티브 코드를 수행할 수 있는 특권을 가로챈 공격자에게는 방어가 무력화된다.
주의사항
- 직렬화 가능 인스턴스 통제 클래스를 작성할 때, 컴파일타임에는 어떤 인스턴스들이 있는지 알 수 없는 경우 열거 타입으로 표현하기 불가능하기 때문에
readResolve()
를 써야한다. readResolve()
의 접근성은 매우 중요하다. final 클래스라면 해당 메서드는 private이어야 한다.- final이 아닌 클래스는 하기 사항들을 고려해야 한다.
- private으로 선언하면 하위 클래스에서 사용할 수 없다.
- protected나 public으로 선언하면 재정의하지 않은 모든 하위 클래스에서 사용할 수 있다.
- protected나 public이면서 하위 클래스에서 재정의하지 않았다면, 하위 클래스의 인스턴스를 역직렬화하면 상위 클래스의 인스턴스를 생성하여 ClassCastException을 일으킬 수 있다.
핵심 정리
불변식을 지키기 위해 인스턴스를 통제해야 한다면 가능한 한 열거 타입을 사용하자.여 의치 않은 상황에서 직렬화와 인스턴스 통제가 모두 필요하다면 readResoIve 메서드를 작성해 넣어야 하고,그 클래스에서 모든 참조 타입 인스턴스 필드를 transient로 선언 해야 한다.
'Java' 카테고리의 다른 글
[Effective Java] 공유 중인 가변 데이터는 동기화해 사용하라 (0) | 2021.07.24 |
---|---|
[Effective Java] 직렬화된 인스턴스 대신 직렬화 프록시 사용을 검토하라 (0) | 2021.07.23 |
[Effective Java] readObject 메서드는 방어적으로 작성하라 (0) | 2021.07.18 |
[Effective Java] 커스텀 직렬화 형태를 고려해보라 (0) | 2021.07.14 |
[Effective Java] Seializable을 구현할지는 신중히 결정하라 (0) | 2021.07.13 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Today
- Yesterday
링크
TAG
- 메인보드#asrock b650m #조립pc #후기이벤트
- strategy
- template
- 영속성
- reactive
- Java
- Spring
- JMeter
- LAMBDA
- exception
- Design Pattern
- observable
- 부하테스트
- template method
- Observer Pattern
- object
- reactive stream
- Serializable
- iterable
- in-memory
- concurrency
- Serialize
- nosql
- Concurrecy
- jvm
- Effective JAVA
- jdk11
- Redis
- 디자인패턴
- gslb
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
글 보관함