클래스 파일
자바 소스코드가 실행이 되려면 자바 컴파일러(javac)를 통해 소스코드를 클래스파일로 변환해야 한다.
컴파일된 클래스파일은 어떤 구조로 되어있을까?
클래스 파일의 데이터 형식
8비트 바이트의 스트림으로 구성된다.
16비트 및 32비트의 데이터는 각각 2개, 4개의 연속된 8비트를 읽어서 구성된다.
멀티바이트의 경우 항상 big endian 순서로 저장된다.
u1 → unsigned 1byte
u2 → unsigned 2byte
u4 → unsigned 4byte
클래스 파일 구조
ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
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];
}
매직넘버
모든 클래스 파일은 0xCAFEBABE라는 매직넘버로 시작한다.
보통 매직넘버는 파일 종류를 식별하는 용도로 사용된다.
클래스 파일 포맷 버전
클래스 파일 버전 값은 클래스로더의 호환성 보장을 위해 꼭 필요한 값이다.
- Java 17 버전으로 빌드한다면 class version 61 ex) 00 00 00 3D
호환되지 않는 버전의 클래스 파일을 로딩하려고 하는 경우 런타임에 UnsupportedClassVersionError
예외가 발생한다.
class file format major versions
Java SE | Released | Major | Supported majors |
---|---|---|---|
8 | March 2014 | 52 | 45 .. 52 |
9 | September 2017 | 53 | 45 .. 53 |
10 | March 2018 | 54 | 45 .. 54 |
11 | September 2018 | 55 | 45 .. 55 |
12 | March 2019 | 56 | 45 .. 56 |
13 | September 2019 | 57 | 45 .. 57 |
14 | March 2020 | 58 | 45 .. 58 |
15 | September 2020 | 59 | 45 .. 59 |
16 | March 2021 | 60 | 45 .. 60 |
17 | September 2021 | 61 | 45 .. 61 |
상수 풀
2바이트의 상수의 개수값이 먼저오고 그 뒤로 코드에 등장하는 상수값이 모여있다.
클래스명, 상수명, 상수 값, 필드명, 메서드명과 같은 값들이 존재한다.
JVM은 코드 실행 시 런타임에 배치된 메모리가 아니라, 해당 상수 풀 테이블을 찾아보고 필요한 값을 참조한다.
액세스 플래그
클래스, 인터페이스와 같은 파일의 속성을 표시한다.
예를 들어 public interface로 정의된 인터페이스의 플래그는 0x0601이다.
- 계산은 다음과 같이 이루어진다.
ACC_PUBLIC
xorACC_INTERFACE
xorACC_ABSTRACT
공식문서에 들어가면 각 플래그에 대한 설명 + 플래그 설정시 동시에 설정되면 안되는 플래그와 같은 설명이 자세하게 나와있다.
Class access and property modifiers
Flag Name | Value | Interpretation |
---|---|---|
ACC_PUBLIC | 0x0001 | Declared public; may be accessed from outside its package. |
ACC_FINAL | 0x0010 | Declared final; no subclasses allowed. |
ACC_SUPER | 0x0020 | Treat superclass methods specially when invoked by the invokespecial instruction. |
ACC_INTERFACE | 0x0200 | Is an interface, not a class. |
ACC_ABSTRACT | 0x0400 | Declared abstract; must not be instantiated. |
ACC_SYNTHETIC | 0x1000 | Declared synthetic; not present in the source code. |
ACC_ANNOTATION | 0x2000 | Declared as an annotation type. |
ACC_ENUM | 0x4000 | Declared as an enum type. |
ACC_MODULE | 0x8000 | Is a module, not a class or interface. |
this_class
클래스명 과 같은 이름을 표현하는 값으로, 상수 풀에서 클래스명과 일치하는 항목의 인덱스를 참조한다.
해당 인덱스의 항목은 CONSTANT_Class_infoclass
형식의 값이어야 한다.
super_class
상수 풀에서 슈퍼 클래스의 이름과 일치하는 항목의 인덱스를 참조한다.
아무것도 상속하지 않는 클래스의 경우 java.lang.Object
의 인덱스 값이 들어있다.
interface, field, method
각각의 개수와, 정보에 대한 값이 들어있다.
interface, field, method를 표시하는 방법이 각각 다르고, 접근자에 대한 플래그도 각각 다르다.
attributes
해당 클래스 파일에서 사용하는 추가 정보의 모음이다. 예) 소스파일명
정해진 클래스 파일의 구조를 확장하는 역할을 한다.
클래스 파일 확인하면서 사용한 툴
IntelliJ plugin - BinEd
IntelliJ plugin - jclasslib Bytecode Viewer
참고 자료
2장 JVM 이야기, 자바 최적화
Class file in Java, File Format
java se11 Class 파일 형식, Oracle
java se17 Class 파일 형식, Oracle