저우즈밍 님의 "JVM 밑바닥까지 파헤치기" 책을 정리한 포스팅 입니다
1. 런타임 데이터 영역

- JVM이 프로그램을 실행하는 동안 데이터를 저장하고 관리하기 위해 사용하는 메모리 구조
영역
| 영역 이름 | 설명 |
주요 특징 및 구성 요소
|
| 메서드 영역 | 클래스 메타데이터 영역 | |
| 힙 영역 | 객체 인스턴스가 저장되는 영역 | - GC 관리 대상 |
| JVM 스택 | 메서드 호출 시마다 생성되는 스레드 기반 스택 | - 스택 프레임 단위 구성 |
| 프로그램 카운터 (PC) | 현재 스레드가 실행 중인 바이트코드의 줄 번호를 저장 |
- 스레드마다 별도 존재
- 네이티브 메서드 실행 시 비어 있음 |
| 네이티브 메서드 스택 | C 등의 네이티브 메서드 실행용 스택 |
- JNI 등 호출 시 사용
|
표) 메서드 영역
더보기
| 구분 | 저장 내용 | 설명 |
| 클래스 메타데이터 | 클래스 이름 | 클래스의 식별 정보 |
| 부모 클래스 정보 | 상속 구조 정보 | |
| 접근 제어 정보 | public, private 등 | |
| 구현 인터페이스 | implements 정보 | |
| 필드 및 메서드 정보 | 필드 이름 및 타입 | 멤버 변수 구조 정보 |
| 메서드 이름 및 시그니처 | 메서드 정의 정보 | |
| 메서드 바이트코드 | 실행할 명령어 코드 | |
| 정적 변수 (static) | 클래스 변수 | 클래스 단위 공유 변수 |
| 런타임 상수 풀 | 리터럴 상수 | 숫자, 문자열 등 |
| 심볼 참조 | 클래스/필드/메서드 이름 정보 |
표) 힙 영역
더보기
| 영역 이름 | 설명 |
주요 특징 및 구성 요소
|
| Young Generation | 새로운 객체가 생성되는 영역 |
- Eden, Survivor 구역
|
| Old Generation | 장기 생존 객체 저장 |
- Full GC 대상
|
| TLAB | 각 스레드 전용의 객체 할당 공간 |
- 동시 할당 충돌 방지, 성능 향상 목적
|
표) JVM 스택 영역
더보기
| 영역 이름 | 설명 |
주요 특징 및 구성 요소
|
| 지역 변수 테이블 | 메서드 내 지역 변수 저장 |
- 32bit 슬롯 단위 (32bit, 64bit)
- 기본 타입, 참조, 반환 주소 등 저장 |
| 피연산자 스택 | 계산에 필요한 값 임시 저장 |
- 연산 명령어 실행 시 사용됨
|
| 동적 링크 및 반환 주소 | 메서드 호출/복귀 정보 유지 |
- 호출자와 피호출자 간 연결 정보
|
2. 핫스팟 가상 머신에서의 객체 들여다보기
객체 메모리 레이아웃
- 객체가 힙에 생성될 때, 크게 3부분으로 메모리 레이아웃이 구성됨
| 구성 요소 | 설명 |
주요 내용 및 목적
|
| 객체 헤더 | JVM이 객체를 관리하기 위해 추가하는 메타데이터 블록 |
마크 워드, 클래스 워드, (배열의 경우 배열 길이 포함)
|
| 인스턴스 데이터 | 실제 필드값이 저장되는 영역 |
- 부모 → 자식 클래스 순서
- 타입 크기 순 정렬 ➡️ 메모리 효율 최적화 |
| 정렬 패딩 | 8바이트 정수배로 맞추기 위해 존재 |
표) 객체 헤더
더보기
| 구성 요소 | 설명 |
주요 내용
|
| Mark word | 객체의 런타임 정보 |
해시코드, GC 나이, 락 상태, 타임스탬프 등
|
| Klass Pointer | 클래스 메타데이터 주소 |
해당 객체가 어떤 클래스의 인스턴스인지 알려줌
|
| 배열 길이 | 배열인 경우만 존재 |
배열의 요소 개수 저장
|
객체 접근 방식
| 항목 | 다이렉트 포인터 방식 | 핸들 방식 |
| 구조 | 객체 참조가 힙의 객체 주소를 직접 가리킴 | 객체 참조가 핸들 테이블의 엔트리를 가리킴 |
| 접근 속도 | 빠름 (중간 참조 없음) |
느림 (간접 참조 필요)
|
| GC 시 객체 이동 | 모든 참조를 업데이트 해야 함 |
핸들만 수정하면 됨
|
| 참조 안정성 | 낮음 (객체 이동 시 참조 오류 가능) |
높음 (핸들이 추상화 계층으로 보호함)
|
객체 생성 과정
- 심볼 참조 확인: new 명령어의 대상이 상수 풀에 존재하는 클래스 심볼인지 확인
- 클래스 로딩 여부 확인: 해당 클래스가 이미 로딩되어 있는지 검사
- (클래스 로딩)
- 메모리 할당
- 필드값 설정 (zero-initialization)
- 객체 헤더 설정: 생성된 객체에 필수 메타정보 설정 (클래스 포인터, 해시코드, GC 나이 등)
- 생성자 호출
과정) new 명령어
더보기
- 상수풀에서 클래스의 심볼 참조를 확인 (CONSTANT_Class → "com/example/User")
- 심볼 참조를 실제 참조로 변환함 (Klass*)
- 힙에 메모리를 할당하고 객체를 생성함
✅ 심볼 참조: 클래스의 이름 정보. 실행 시점에 실제 객체 생성을 위한 메타데이터의 포인터로 변환됨
3. OutOfMemoryError
- JVM이 새로운 객체나 메모리를 할당하려 했으나, 사용할 수 있는 메모리가 부족할 때 발생하는 에러
| 오버플로 종류 | 발생 조건/설명 | 예외 클래스 |
| Heap OOM | 힙에 객체를 더이상 할당이 불가함 | OutOfMemoryError |
| Metaspace OOM | 메타스페이스 초과 | OutOfMemoryError |
| Native Memory OOM | ByteBuffer.allocateDirect() 사용 시 설정된 한도 초과 | OutOfMemoryError |
| 스택 오버플로 | 재귀로 스택 프레임 과다 | StackOverflowError |
옵션) Heap OOM
더보기
- -Xms: 최소 힙 크기 지정
- -Xmx: 최대 힙 크기 지정
- -XX:+HeapDumpOnOutOfMemoryError: OOM 발생 시 힙 덤프 생성
옵션) 스택 오버플로
더보기
- -Xss: 스레드당 스택 크기 설정
옵션) Metaspace OOM
더보기
- -XX:MetaspaceSize: 초기 메타스페이스 크기
- -XX:MaxMetaspaceSize: 최대 메타스페이스 크기
- -XX:MinMetaspaceFreeRatio: 최소 여유 공간 비율 설정
옵션) Native Memory OOM
더보기
- -XX:MaxDirectMemorySize: 다이렉트 메모리 최대 사용량 제한
출처
'Java' 카테고리의 다른 글
| [JVM 밑바닥까지 파헤치기] 3-2. 가비지 컬렉터와 메모리 할당 전략: 가비지 컬렉션 (0) | 2024.12.21 |
|---|---|
| [JVM 밑바닥까지 파헤치기] 3-1. 가비지 컬렉터와 메모리 할당 전략: 회수 (1) | 2024.12.19 |
| [JVM 밑바닥까지 파헤치기] 1. 자바 기술 시스템 소개 (3) | 2024.12.19 |
| [Java][Tutorial] 1-3. Learning the Java Language: Classes and Objects (0) | 2024.01.14 |
| [Java][Tutorial] 1-2. Learning the Java Language: Language Basics (0) | 2024.01.14 |