백엔드 면접 용어 사전
Java·객체지향JVM 메모리 · JVM

JVM 런타임 데이터 영역

메서드 영역·힙·스택·PC·네이티브 스택으로 나뉜 JVM의 메모리 구조. 스택은 스레드마다, 힙은 공유다.

JVM이 프로그램 실행 중에 사용하는 메모리 구획들. 어떤 것이 스레드마다 따로이고 어떤 것이 공유되는지가 핵심이다.

전체 구조

┌──────────── 모든 스레드가 공유 ────────────────┐
│  힙 (Heap)                                     │
│    Young(Eden, Survivor 0/1)  Old              │
│  메서드 영역 (Metaspace)                       │
│    클래스 메타데이터 · static · 런타임 상수 풀 │
└────────────────────────────────────────────────┘

┌──────────── 스레드마다 하나씩 ─────────────────┐
│  JVM 스택   — 스택 프레임(지역변수·피연산자)   │
│  PC 레지스터 — 현재 실행 중인 바이트코드 주소  │
│  네이티브 메서드 스택 — JNI 호출용             │
└────────────────────────────────────────────────┘

힙 — 객체가 사는 곳

new로 만든 모든 객체와 배열이 여기 있다. GC의 대상이다.

Young Generation                  Old Generation
┌─────┬────────┬────────┐        ┌────────────────┐
│Eden │Survivor│Survivor│  ───►  │  오래 산 객체  │
│     │   0    │   1    │        │                │
└─────┴────────┴────────┘        └────────────────┘
  ↑ 새 객체는 여기서 태어난다

왜 나누나 — 약한 세대 가설

  • "대부분의 객체는 금방 죽는다"
  • 갓 만든 객체만 모아 자주 청소하면 적은 비용으로 많이 회수된다 실제로 대부분의 객체(요청 처리용 임시 객체 등)는 몇 밀리초 만에 쓰레기가 된다.

Survivor를 거칠 때마다 age가 오르고, 임계치를 넘으면 Old로 승격된다.

스택 — 실행 흐름이 사는 곳

메서드를 호출할 때마다 스택 프레임이 쌓인다.

프레임에 담기는 것

  • 지역 변수 배열 (매개변수 포함)
  • 피연산자 스택 (계산 중간값)
  • 프레임 데이터 (상수 풀 참조, 반환 주소)

스레드마다 따로이므로 지역 변수는 스레드 안전하다. -Xss 로 크기를 조절하며, 초과하면 StackOverflowError다.

힙과 스택 — 참조와 실체

void method() {
    Person p = new Person("김철수");
}
스택 (이 스레드만)          힙 (모두 공유)
┌──────────┐              ┌─────────────────┐
│ p: 0x1A3F│ ───────────► │ Person 객체     │
└──────────┘              │ name → "김철수" │
   참조 변수는 스택       └─────────────────┘
                            실제 객체는 힙

변수 p는 스택에, 객체는 힙에 있다. 그래서 다른 스레드에 p를 넘기면 같은 객체를 공유하게 된다 — 여기서 동시성 문제가 시작된다.

메서드 영역 (Metaspace)

클래스 정보, static 변수, 상수 풀이 있다.

자바 8에서 큰 변화가 있었다. ~ 자바 7 : PermGen (힙 안. 고정 크기)

  • 클래스를 많이 로드하면 OutOfMemoryError: PermGen space
  • 크기 예측이 어려워 악명 높았다

자바 8 ~ : Metaspace (네이티브 메모리. 기본 무제한)

  • OOM은 줄었지만, 방치하면 시스템 메모리를 다 먹는다
  • -XX:MaxMetaspaceSize 로 상한을 두는 것이 권장

Metaspace가 계속 늘어난다면 클래스로더 누수를 의심한다 — 동적 프록시·리플렉션·잦은 재배포에서 발생한다.

OOM 메시지로 원인 찾기 — 실무 진단

메시지원인
Java heap space힙 부족. 누수 또는 -Xmx 부족
Metaspace클래스 과다 로드·클래스로더 누수
unable to create new native thread스레드 과다(OS 한계)
GC overhead limit exceededGC에 98% 시간을 쓰는데 2% 미만 회수
Requested array size exceeds VM limit배열 크기가 비정상

메시지가 어느 영역이 터졌는지 알려 준다. 이 표를 아는 것이 장애 대응의 출발점이다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — Java·객체지향 — OOP·JVM·GC·컬렉션