Post

[CS] Java Deep Dive: JVM & Memory Management

[CS] Java Deep Dive: JVM & Memory Management

[CS] Java Deep Dive: JVM & Memory Management

  • OS 독립성: 바이트코드(.class)는 JVM 위에서 실행되므로, 윈도우에서 짠 코드가 리눅스 서버에서도 동일하게 작동함.

정리

1. JVM의 핵심 역할: 가상화와 자동화

  • OS 독립성: 바이트코드(.class)는 JVM 위에서 실행되므로, 윈도우에서 짠 코드가 리눅스 서버에서도 동일하게 작동함.

  • 자동 메모리 관리: C/C++처럼 개발자가 free()를 호출할 필요 없이, JVM이 알아서 가비지(Garbage)를 치움.

2. JVM 내부 구조 상세 (Internal Architecture)

2.1 Class Loader: “클래스를 언제, 어떻게 가져오는가?”

  • Lazy Loading (지연 로딩): 모든 클래스를 한꺼번에 올리지 않고, 실제 코드에서 참조될 때 로드함.

  • 단계: Loading(읽기) → Linking(검증/준비) → Initialization(static 값 초기화).

2.2 Execution Engine: “바이트코드를 기계어로 바꾸는 두 가지 방식”

  • Interpreter: 바이트코드를 한 줄씩 읽어서 실행. 빠르지만 반복 작업엔 비효율적.

  • JIT (Just-In-Time) Compiler: 자주 실행되는 ‘Hot Method’를 찾아내서 통째로 기계어로 컴파일한 뒤 캐싱함.

  • 예시: 반복문이 1만 번 돌아가면 인터프리터 대신 JIT가 개입해 실행 속도를 폭발적으로 높임.

3. Runtime Data Area: “데이터가 어디에 저장되는가?”

3.1 Stack vs Heap (가장 중요한 구분)

실제 코드를 예시로 보면 이해가 빠릅니다.

1
2
3
4
public void study() {
    int age = 25;              // Stack에 저장 (기본 타입 변수)
    String name = new String("Gemini"); // 'name' 레퍼런스는 Stack, "Gemini" 객체는 Heap에 저장
}

3.2 Method Area (Static Area)

  • 클래스 이름, 부모 클래스 이름, 메서드 데이터, static 변수가 저장됨.

  • 프로그램 시작부터 종료까지 메모리에 남아있으므로 과도한 static 사용은 메모리 낭비를 초래함.

4. 가비지 컬렉션 (GC) 상세 메커니즘

4.1 Reachability: “누구를 지울 것인가?”

  • Root Set: Stack의 변수, Static 변수 등에서 참조가 시작됨.

  • Reachable: Root Set으로부터 연결 고리가 있는 객체. (생존)

  • Unreachable: 연결 고리가 끊긴 객체. (GC 대상)

4.2 Heap의 세대별 관리 (Generational Strategy)

객체의 90%는 금방 쓰레기가 된다는 통계적 사실에 기반합니다.

  1. Young Generation (Eden, S0, S1):
  • 새로 만든 객체가 들어감. 꽉 차면 Minor GC 발생.

  • 살아남은 객체는 Survivor 영역으로 이동하며 ‘Age’가 올라감.

  1. Old Generation:
  • 일정 Age(보통 15회) 이상 살아남은 ‘장수 객체’가 이동함.

  • 여기가 꽉 차면 Major GC (Full GC) 발생. (이때 Stop-the-world 발생)

5. 실무 적용 및 트러블슈팅 (Use Case)

5.1 Stop-the-world (STW)

  • 현상: GC를 실행하기 위해 JVM이 애플리케이션의 모든 스레드를 일시 정지시키는 것.

  • 해결: 최신 GC(G1, ZGC)는 이 멈춤 시간을 밀리초(ms) 단위로 줄이는 방향으로 발전 중.

5.2 메모리 누수(Memory Leak) 사례

  • 정적 컬렉션 사용: static List에 객체를 계속 넣고 비우지 않으면, GC가 “아직 참조 중이네?”라고 판단해 절대 치우지 않음. 결국 OutOfMemoryError(OOM) 발생.

  • 리소스 미폐쇄: DB 연결(Connection)이나 파일 스트림을 열고 close() 하지 않으면 메모리가 점유된 상태로 남음.

This post is licensed under CC BY 4.0 by the author.