8. 불변 객체와 String 클래스
1. 불변(Immutable, 읽기 전용) 객체의 논리적 개념
사이드 이펙트와 참조자
특정 인스턴스에 대한 참조는 여러 개가 될 수 있으며 이를 막을 수도 없다.
문법적으로 막아놓지 않는다.. (컴파일 오류 발생 X)
모든 참조는 대상 인스턴스에 대한 읽기, 쓰기, 접근이 모두 허용된다.
인스턴스에 대한 무결성을 보장해야 하는 구조에서는 (논리적) 문제가 발생할 수 있다.
예를 들어, 여러 스레드가 각각의 값을 가져야하지만, 동일한 값을 사용하는 (논리적) 문제가 발생한다.
의도하지 않은 값을 사용하게 된다.
때문에, 동시성이 발생하는 환경에서는 동기화가 중요한 케이스이다.
2. 불변 객체의 특성 정의
모든 필드를
final
선언함으로써 상수화한 클래스 (무결성)필드 값을 변경해야 한다면 새로운 사본 클래스를 생성하면서 원하는 수정된 초기값을 기술해 반환하는 구조로 개발 (원자성 보장)
대표적 불변객체
String
,Wrapper class
6. JVM 이 문자열 상수를 관리하는 구조
📌 1. C/C++과의 비교: 정적 메모리에 문자열 상수 저장
C/C++에서 .exe
파일을 만들면, 문자열 리터럴은 실행 파일의 정적 메모리 영역에 포함됩니다.
이때 동일한 문자열은 하나의 주소로 공유되며, 실행 시 별도로 할당되지 않습니다.
예:
"hello"
가 여러 번 등장해도 하나의 메모리 주소에 저장됨→
"hello"
를 참조하는 포인터 주소는 모두 동일
📌 2. Java에서 문자열 리터럴은 ‘시점’에 따라 관리 위치가 다르다
Java에서는 문자열 리터럴도 상수로 관리되지만, JVM이 실행되며 거치는 시점마다 저장 위치가 다릅니다.
🔸 컴파일 시점 (.class
파일 생성)
Java 소스 코드 내
"hello"
같은 리터럴은.class
파일 내 Constant Pool에CONSTANT_String_info
형태로 메타데이터가 저장됩니다.이 시점에서는 아직
java.lang.String
객체는 생성되지 않습니다.
🔸 클래스 로딩 시점 (Runtime Constant Pool)
클래스 로딩 시,
.class
파일의 Constant Pool이 JVM의 Runtime Constant Pool으로 적재됩니다.이 영역은 JVM의 Method Area(Java 8부터는 Metaspace) 내부에 존재하며, 문자열 리터럴도 심볼릭 참조 형태로 유지됩니다.
🔸 사용 시점 (실제 실행 중 리터럴 사용)
최초로 문자열 리터럴을 참조할 때, JVM은 해당 문자열을 Heap에 String 객체로 생성하고 String Constant Pool (intern pool)에 등록합니다.
이후 동일한 리터럴이 다시 등장하면, JVM은 intern pool에 등록된 String 객체를 재사용합니다.
📌 3. String Constant Pool (Intern Pool)
intern pool은 Java의 Heap 영역에 존재하며, 동일한 문자열 리터럴이 여러 번 생성되는 것을 방지합니다.
"hello"
처럼 문자열 리터럴은 자동으로 intern 처리되지만,new String("hello")
와 같이 명시적으로 객체를 생성한 경우에는 intern pool에 등록되지 않습니다.
Java 6까지는 intern pool이 PermGen에 존재했지만, Java 7부터는 Heap으로 이동하여 메모리 유연성이 향상되었습니다.
📌 4. 구조 요약
컴파일 시점
.class
파일의 Constant Pool
문자열 리터럴의 메타 정보 (CONSTANT_String_info
)
클래스 로딩 시점
Method Area의 Runtime Constant Pool
심볼릭 참조 정보
사용 시점
Heap 내부의 String Constant Pool
실제 String
객체 (intern 처리)
📌 5. JVM이 문자열 리터럴을 효율적으로 처리하는 이유
중복 객체 생성을 방지해 메모리 절약
동일한 문자열 리터럴 비교 시
==
으로 비교 가능 → 성능 최적화예측 가능한 메모리 모델로 GC 최적화도 유리
🧠 함께 알아두면 좋은 내용
intern()
메서드는 수동으로 문자열을 intern pool에 등록하거나 검색할 수 있게 해줍니다.JVM의 GC 대상이 되는 String pool은 Java 7 이후 Heap 영역에 존재하기 때문에 사용하지 않는 intern 문자열은 GC로 회수될 수 있습니다.
String Deduplication 기능은 G1 GC 환경에서
-XX:+UseStringDeduplication
을 통해 내용이 같은 String 객체의 내부 char 배열을 공유하여 추가적인 메모리 절약을 시도합니다.
Last updated