본문으로 건너뛰기

자바 클래스 파일 구조

· 약 6분

클래스 파일

자바 소스코드가 실행이 되려면 자바 컴파일러(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 SEReleasedMajorSupported majors
8March 20145245 .. 52
9September 20175345 .. 53
10March 20185445 .. 54
11September 20185545 .. 55
12March 20195645 .. 56
13September 20195745 .. 57
14March 20205845 .. 58
15September 20205945 .. 59
16March 20216045 .. 60
17September 20216145 .. 61

상수 풀

2바이트의 상수의 개수값이 먼저오고 그 뒤로 코드에 등장하는 상수값이 모여있다.
클래스명, 상수명, 상수 값, 필드명, 메서드명과 같은 값들이 존재한다.
JVM은 코드 실행 시 런타임에 배치된 메모리가 아니라, 해당 상수 풀 테이블을 찾아보고 필요한 값을 참조한다.

액세스 플래그

클래스, 인터페이스와 같은 파일의 속성을 표시한다.
예를 들어 public interface로 정의된 인터페이스의 플래그는 0x0601이다.

  • 계산은 다음과 같이 이루어진다. ACC_PUBLIC xor ACC_INTERFACE xor ACC_ABSTRACT

공식문서에 들어가면 각 플래그에 대한 설명 + 플래그 설정시 동시에 설정되면 안되는 플래그와 같은 설명이 자세하게 나와있다.

Class access and property modifiers

Flag NameValueInterpretation
ACC_PUBLIC0x0001Declared public; may be accessed from outside its package.
ACC_FINAL0x0010Declared final; no subclasses allowed.
ACC_SUPER0x0020Treat superclass methods specially when invoked by the invokespecial instruction.
ACC_INTERFACE0x0200Is an interface, not a class.
ACC_ABSTRACT0x0400Declared abstract; must not be instantiated.
ACC_SYNTHETIC0x1000Declared synthetic; not present in the source code.
ACC_ANNOTATION0x2000Declared as an annotation type.
ACC_ENUM0x4000Declared as an enum type.
ACC_MODULE0x8000Is 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