String의 intern() 메서드에 대해 공부하다 보면 "절대 쓰지 말라"는 권고를 접할 수 있습니다.
intern()은 힙 영역에 생성된 String 객체를 String Constant Pool로 옮겨 메모리를 절약하고 중복을 줄이기 위한 메서드지만, 잘못 사용하면 성능 문제가 발생할 수 있습니다.
String Constant Pool 은 자바 7 이후에 메서드 영역에서 힙 영역으로 옮겨졌습니다. 즉 GC 의 대상이 된다는 것입니다.
intern() 메서드를 사용할 때 발생할 수 있는 문제점
- Full GC 발생 가능성 증가로 인한 성능 저하
- 객체는 처음 생성 시 에덴 영역에 할당되고, 참조되지 않으면 Minor GC에서 쉽게 수거됩니다. 하지만 intern()으로 객체를 String Constant Pool에 강제로 넣으면 이 객체는 더 이상 쉽게 수거되지 않습니다.
- String Constant Pool이 가득 차면 Full GC가 발생할 수 있으며, Full GC는 애플리케이션을 멈추는 Stop-the-World 시간을 증가시켜 성능에 부정적인 영향을 줍니다. 가능하다면 Minor GC에서 대부분의 객체를 수거하는 것이 효율적이므로 자주 참조되지 않는 객체에 intern()을 남용하는 것은 성능 오버헤드를 유발할 수 있습니다.
- synchronized로 인한 성능 병목
- intern() 메서드는 synchronized로 보호되므로, 여러 스레드가 동시에 접근할 때 하나의 스레드만 접근할 수 있습니다. 예를 들어, 100개의 스레드가 intern()을 호출하면 한 스레드가 작업을 완료할 때까지 나머지 99개의 스레드가 대기해야 하므로, 멀티스레드 환경에서 성능 병목이 발생할 수 있습니다.
- 메모리 누수 가능성
- String Constant Pool에 들어간 문자열은 JVM이 종료될 때까지 유지됩니다. 따라서 자주 사용하지 않는 문자열을 intern()하면 메모리 누수가 발생할 수 있으며, 특히 서버 환경처럼 장기간 실행되는 경우에는 메모리 문제로 이어질 수 있습니다.
intern() 메서드 사용 시 고려해야 할 사항
- 특정 상황에서 유용한 경우
intern()은 자주 반복되며 고정된 패턴의 문자열이 많을 때 메모리를 절약하고 중복 생성을 줄일 수 있어 유용할 수 있습니다. 하지만 이 경우에도 성능 테스트를 통해 풀 메모리 관리를 충분히 검토한 후 사용 여부를 결정해야 합니다. 또한 고정된 패턴이 확실하다 하면 Eunm 클래스나 문자 상수로 정의해 놓는 게 일반적입니다. - Java 버전 변화 최신 Java 버전에서는 String Constant Pool이 힙(heap) 영역에 위치하게 되면서 관리가 개선되었습니다. 하지만 Full GC 문제는 여전히 존재하기 때문에, Java 버전과 JVM 설정을 고려해 신중히 사용해야 합니다.
- 대안 고려
성능 최적화를 위해 intern()을 고려 중이라면, ConcurrentHashMap 같은 캐시 구조로 자주 사용되는 문자열을 저장하는 것도 하나의 대안이 될 수 있습니다. 이를 통해 메모리 중복을 방지하면서도 성능 저하를 피할 수 있습니다.
결론
intern() 메서드는 메모리 절약에 도움이 되지만, 성능 저하 가능성이 크므로 남용하지 않는 것이 좋습니다. 만약 사용해야 한다면, 성능 병목, GC 부하, 메모리 누수 등의 문제를 충분히 검토하고 적절한 대안과 함께 고려하는 것이 안전합니다.
'JAVA' 카테고리의 다른 글
[JAVA ]Set , Map 알아보기, 로드 팩터 (Load Factor)와 HashSet의 리해싱 (0) | 2024.11.19 |
---|---|
유니코드, UTF-8, 직렬화 (1) | 2024.11.18 |
[JAVA] 동기화 - synchronized (1) | 2024.11.13 |
[JAVA] 스레드 Interrupted (0) | 2024.11.13 |
[JAVA] 스레드 Join (0) | 2024.11.12 |