저우즈밍 님의 "JVM 밑바닥까지 파헤치기" 책을 정리한 포스팅 입니다
1. 클래스 파일 (.class)
- 하나의 클래스 또는 인터페이스의 구조와 바이트코드를 담고 있는 파일 (빅 엔디언 방식)
- ✅ JVM이 실행할 수 있도록 컴파일된 결과물
- ✅ 하위 호환성을 유지하며 확장됨 (최신 JVM 버전에서도 항상 실행됨)
메모리 저장 방식) 빅 엔디언
더보기
- 가장 큰 자리를 먼저 저장하는 방식 (사람이 읽는 방식과 같음)
- 네트워크 바이트 오더
- ex) 0x1234 → 12 34
2. 구조
| 항목 | 설명 | 특징 |
| 매직 넘버 | 파일 형식을 식별하기 위한 고정 값 | 값은 0xCAFEBABE로 고정됨 |
| 버전 번호 | 이 클래스 파일이 어떤 JVM 스펙에 맞춰 생성되었는지 나타내는 값 | 실행 가능 여부를 결정함 |
| 상수 풀 | 클래스에서 사용하는 모든 상수와 심볼 참조를 저장하는 테이블 |
심벌 참조, 리터럴 상수 저장소
|
| 접근 플래그 |
클래스/인터페이스의 접근 수준
|
e.g) ACC_PUBLIC, ACC_FINAL
|
| 클래스 인덱스 | 현재 클래스와 부모 클래스를 가리키는 인덱스 |
상수 풀 인덱스로 클래스 이름을 찾음
|
| 필드 테이블 |
클래스에 정의된 멤버 변수들의 정보 저장
|
e.g) 이름, 타입, 접근 플래그 등
|
| 메서드 테이블 |
클래스에 정의된 메서드들에 대한 정보 저장
|
|
| 속성 테이블 |
각 필드/메서드/클래스의 속성 저장
|
e.g) Code, LineNumberTable
|
예시) 클래스 파일 구조
더보기
ClassFile {
u4 magic; // 매직 넘버 (0xCAFEBABE)
u2 minor_version; // 클래스 파일의 마이너 버전
u2 major_version; // 클래스 파일의 메이저 버전
u2 constant_pool_count; // 상수 풀 항목의 개수
cp_info constant_pool[constant_pool_count-1]; // 상수 풀 테이블
u2 access_flags; // 접근 플래그 (public, final 등)
u2 this_class; // 현재 클래스 정보 (상수 풀 인덱스)
u2 super_class; // 슈퍼 클래스 정보 (상수 풀 인덱스)
u2 interfaces_count; // 구현된 인터페이스 개수
u2 interfaces[interfaces_count]; // 인터페이스 목록 (상수 풀 인덱스)
u2 fields_count; // 필드 개수
field_info fields[fields_count]; // 필드 테이블
u2 methods_count; // 메서드 개수
method_info methods[methods_count];// 메서드 테이블
u2 attributes_count; // 속성 개수
attribute_info attributes[attributes_count]; // 속성 테이블
}
예시) 필드/메서드 테이블 구조
더보기
struct {
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attributes_count];
}
- access_flags: 접근 제어자 + 특성 정보 (ACC_PUBLIC, ACC_PRIVATE, ACC_STATIC, ACC_SYNCHRONIZED)
- name_index: 상수 풀의 CONSTANT_Utf8 인덱스
- descriptor_index: 타입 정보를 표현하는 문자열
예시) 속성 테이블
더보기
struct {
u2 attribute_name_index;
u4 attribute_length;
u1 info[attribute_length]; // 실제 속성 데이터
}
- attribute_name_index: 상수 풀의 CONSTANT_Utf8 인덱스 (속성의 이름을 문자열로 참조함)
- attribute_length: 해당 attrubute의 실제 바이트 길이
- info[]: 실제 속성 데이터 (attribute마다 내부 구조 완전 다름)
표) descriptor_index 타입 정보
더보기
| 자바 타입 | 디스크립터 |
| int | I |
| long | J |
| double | D |
| boolean | Z |
| String | Ljava/lang/String; |
| int[] | [I |
| 메서드 | (I)Ljava/lang/String; |
표) attribute 종류
더보기
| Attribute 이름 | 적용 위치 | 역할 | 중요 포인트 |
| Code | 메서드 | 실제 바이트코드 저장 | JVM이 실행하는 코드가 여기 있음 |
| LineNumberTable | Code 내부 | 바이트코드 ↔ 소스 줄 번호 매핑 | 디버깅용 |
| LocalVariableTable | Code 내부 | 로컬 변수 이름/범위 정보 | 디버깅용 |
| StackMapTable | Code 내부 | 타입 검증 정보 | 바이트코드 검증에 필수 |
| SourceFile | 클래스 | 원본 .java 파일명 | 디버깅 정보 |
| ConstantValue | 필드 | static final 상수 값 저장 | 컴파일 타임 상수 |
| Exceptions | 메서드 | throws 목록 | 예외 선언 정보 |
| Signature | 클래스/필드/메서드 | 제네릭 타입 정보 | 런타임에는 소거되지만 여기 저장됨 |
| InnerClasses | 클래스 | 내부 클래스 정보 | 컴파일러 생성 메타데이터 |
| EnclosingMethod | 클래스 | 익명/로컬 클래스 외부 메서드 정보 | 람다/익명 클래스 관련 |
| RuntimeVisibleAnnotations | 클래스/필드/메서드 | 런타임 유지 애노테이션 | 리플렉션 가능 |
| RuntimeInvisibleAnnotations | 클래스/필드/메서드 | 컴파일 전용 애노테이션 | 런타임에는 제거 |
| AnnotationDefault | 메서드 | 애노테이션 기본값 | 애노테이션 정의 시 사용 |
| BootstrapMethods | 클래스 | invokedynamic 부트스트랩 정보 | 람다/스트림 핵심 |
| Module | 클래스 | Java 9 모듈 정보 | JPMS 지원 |
| Record | 클래스 | Java Record 메타정보 | Java 14+ |
| NestMembers / NestHost | 클래스 | 중첩 클래스 접근 제어 | Java 11+ |
표) 상수 풀
더보기
| 구분 | 설명 | 예시 |
| 리터럴 |
문자열, 숫자 값 등 고정 리터럴 값
|
- CONSTANT_Integer
- CONSTANT_Long - CONSTANT_Utf8 |
| 심볼 참조 |
문자열 기반의 참조 정보
|
- CONSTANT_Class - CONSTANT_Methodref - CONSTANT_Fieldref - CONSTANT_InterfaceMethodref - CONSTANT_NameAndType |
| 동적 링크 |
런타임 중 클래스 로딩/링크에 필요한 참조
|
- CONSTANT_MethoHandler - CONSTANT_MethoType - CONSTANT_InvokeDynamic (람다) |
'Java' 카테고리의 다른 글
| [JVM 밑바닥까지 파헤치기] 7-1. 클래스 로딩 매커니즘: 클래스 로딩 처리 과정 (3) | 2024.12.23 |
|---|---|
| [JVM 밑바닥까지 파헤치기] 6-2. 클래스 파일 구조: 바이트코드 명령어 (2) | 2024.12.22 |
| [JVM 밑바닥까지 파헤치기] 3-5. 가비지 컬렉터와 메모리 할당 전략: 저지연 가비지 컬렉터 (0) | 2024.12.21 |
| [JVM 밑바닥까지 파헤치기] 3-4. 가비지 컬렉터와 메모리 할당 전략: 클래식 가비지 컬렉터 (0) | 2024.12.21 |
| [JVM 밑바닥까지 파헤치기] 3-3. 가비지 컬렉터와 메모리 할당 전략: 구현 (2) | 2024.12.21 |