2025-03-27

JVM 메모리 구조와 클래스 로딩 (Constant Pool과 intern())

JVMJava메모리Constant Poolintern

JVM 메모리 구조와 클래스 로딩 (Constant Pool과 intern())


Runtime Data Area

JVM이 실행 시 메모리를 여러 영역으로 할당합니다.

1. Method Area

클래스 로딩 시 클래스 메타정보, static 변수, constant pool 복사본이 저장됩니다. Runtime Constant Pool이 이 영역의 일부로 포함됩니다. Java 8 이후부터 Metaspace(네이티브 메모리)에 저장됩니다.

public class StaticExample {
    static String val = "loaded";
 
    static {
        System.out.println("StaticExample loaded!");
    }
}
 
public class LoadTest {
    public static void main(String[] args) throws Exception {
        Class.forName("StaticExample"); // Method Area에 로딩됨
    }
}
 
// javac StaticExample.java LoadTest.java
// java LoadTest
 
/**
 * 출력결과
 * Before loading
 * StaticExample loaded!
 * After loading
 */

2. Heap

new로 생성된 모든 객체는 Heap에 저장됩니다. intern된 문자열도 Java 7부터 Heap에 존재합니다.

String heapString = new String("apple"); // Heap에 생성

3. Stack

각 스레드는 자체 JVM Stack을 유지합니다. 메서드가 호출되면 프레임이 생성되고 LIFO 순서로 제거됩니다. 지역 변수와 매개변수가 저장됩니다.

public void add(int a, int b) {
    int sum = a + b; // Stack에 저장됨
}

4. Program Counter (PC Register)

현재 실행 중인 JVM 명령어의 위치를 추적합니다. 스레드당 하나씩 존재합니다.

5. Native Method Stack

네이티브 코드 실행(C/C++ via JNI)을 위한 영역입니다.


Constant Pool & Runtime Constant Pool

Constant Pool

컴파일된 .class 파일 내에 존재하며, 컴파일 타임에 생성됩니다. 문자열 리터럴, 클래스 이름, 메서드 이름, 필드 이름, 타입 등의 상수 정보를 저장합니다. 각 클래스마다 하나씩 존재하며, JVM은 런타임 시 메서드 호출과 필드 접근에 이 정보를 사용합니다.

String s = "Hello";
// "Hello"는 컴파일 타임에 상수 풀에 저장됨

Runtime Constant Pool

JVM이 클래스를 메모리에 로드할 때 생성되는 상수 풀의 런타임 버전입니다. 클래스 로더가 .class 파일을 로딩할 때 상수 풀 정보를 복사하며, 동적으로 추가된 상수와 참조도 포함할 수 있습니다.

String a = "Hi";
String b = "Hi";
System.out.println(a == b); // true
// "Hi"는 상수 풀에 저장되고, a, b는 같은 객체를 참조함

정리

  • Constant Pool은 .class 파일에 존재하고, Runtime Constant Pool이 Method Area에서 이를 참조
  • Heap은 객체 저장소, Stack은 실행 컨텍스트 유지
  • intern()은 문자열을 Heap 내 intern pool에 연결