ClassFile - 2

2024-05-18

entrance

Intro

ClassFile-1 에 이어서 클래스파일의 속성에 대해서 정리합니다.

ClassFile Attribute

Classfile 클래스파일은 클래스 메타 정보와 속성으로 구성되며 속성은 클래스의 메타 정보를 제외한 final,Exceptions, SourceFile, 제네릭 타입, Code속성 등의 클래스를 풍부하게 하는 기능을 나타냅니다. 속성class_file, field_info, method_info,Code속성 등에서 목적에 맞게 존재합니다.

attribute_info { u2 attribute_name_index; u4 attribute_length; u1 info[attribute_length]; }

모든 속성들의 기본적인 속성 테이블은 다음과 같습니다. u2 attribute_name_indexCONSTANT_utf8타입 상수를 참조해 표현하며, attribute_length의 길이는 u4타입으로 나타냅니다. JVM에서는 미리 정의되어 있는 기존 속성 이름과 중복되지 않는 한 자체 제작한 컴파일러가 새로운 속성 정보를 추가해서 사용할 수 있습니다.

JVM에서 정의한 속성은 최초 9개에서 JDK21에서는 총 30개로 늘었습니다. 간단하게 정리하면 아래와 같습니다.

Attribute 쓰이는 위치 의미
InnerClasses 클래스 내부 클래스 및 인터페이스에 대한 정보
EnclosingMethod 클래스 내부 클래스가 포함된 메서드에 대한 정보
Synthetic 클래스,필드,메서드 컴파일러가 생성한 클래스를 나타내는 정보
Signature 필드,메서드 제네릭 타입 정보가 포함된 메서드나 클래스의 시그니처
SourceFile 클래스 소스 파일 이름
SourceDebugExtension 클래스 디버깅 정보를 확장하는 데 사용되는 사용자 정의 정보
Deprecated 메서드, 필드 더 이상 사용되지 않는 클래스, 메서드 또는 필드를 나타냄
RuntimeVisibleAnnotations 클래스,메서드,필드 런타임에 보이는 애노테이션
RuntimeInvisibleAnnotations 클래스,메서드,필드 런타임에 보이지 않는 애노테이션
RuntimeVisibleParameterAnnotations 메서드 메서드 파라미터에 대한 런타임에 보이는 애노테이션
RuntimeInvisibleParameterAnnotations 메서드 메서드 파라미터에 대한 런타임에 보이지 않는 애노테이션
AnnotationDefault 메서드 애노테이션 타입 요소의 기본값
BootstrapMethods 클래스 파일 런타임에 동적으로 호출할 메서드에 대한 부트스트랩 메서드 정보
Module 클래스 파일 모듈 시스템 정보를 포함
ModulePackages 클래스 파일 모듈에 포함된 패키지들의 목록
ModuleMainClass 클래스 파일 모듈의 메인 클래스를 지정
NestHost 클래스 파일 현재 클래스의 호스트 클래스를 지정
NestMembers 클래스 파일 현재 클래스의 네스트 멤버 클래스를 지정
Record 클래스 파일 레코드 클래스에 대한 정보
ConstantValue 필드 테이블 final 키워드로 정의된 상수값
Code 메서드 테이블 자바 코드가 컴파일된 결과인 바이트 코드 명령어들
StackMapTable Code속성 스택 프레임의 변화를 나타내는 정보
Exceptions 메서드 테이블 메서드가 던질 수 있는 예외 클래스들
LineNumberTable Code속성 자바 소스 코드의 줄 번호와 바이트 코드 오프셋의 매핑
LocalVariableTable Code속성 메서드의 로컬 변수에 대한 디버그 정보
LocalVariableTypeTable 클래스 로컬 변수의 제네릭 타입 정보
MethodParameters 메서드 테이블 메서드의 매개변수에 대한 정보

몇 개의 주요한 속성들을 살펴보겠습니다.

Code 속성

아무래도 소스 코드를 나타내는 Code속성이 가장 중요합니다. 메서드 본문 코드는 자바 컴파일러에 의해 최종적으로 바이트코드 명령어로 변환된 후 Code속성에 저장됩니다. 인터페이스추상 메서드Code속성이 없습니다.

Code_attribute { u2 attribute_name_index; // 상수풀을 참조하여 속성 이름을 가리킵니다. u4 attribute_length; // 속성의 길이 u2 max_stack; // 피연산자 스택의 최대 깊이 u2 max_locals; // 지역 변수 테이블에 필요한 저장소 공간 u4 code_length; // 코드 길이 u1 code[code_length]; // 바이트코드 스트림 u2 exception_table_length; //메서드 예외 테이블 길이 { u2 start_pc; u2 end_pc; u2 handler_pc; u2 catch_type; } exception_table[exception_table_length]; // 예외 테이블 u2 attributes_count; // Code속성에 존재하는 속성수 attribute_info attributes[attributes_count]; // Code속성에 존재하는 속성 }

max_stack은 피연산자 스택의 최대 깊이를 뜻합니다. 메서드가 실행되는 동안 피연산자 스택은 이 깊이를 절대 넘을 수 없습니다. JVMmax_stack을 참고하여 피연산자 스택을 스택프레임에 할당합니다.

max_locals는 지역 변수 테이블에 필요한 저장소 공간입니다. max_local에는 byte,char,double,long과 같은 변수의 메모리가 할당됩니다. 메서드 매개변수this매개변수 등 메서드 본문에 정의된 모든 지역 변수가 max_local에 저장됩니다.

code_length는 자바 소스 코드가 컴파일되어 생성된 바이트코드 명령어들의 길이를 나타냅니다. codecode_length만큼 바이토코드를 저장한 바이트코드 스트림입니다.

exception_table은 해당 메서드에서 명시적으로 처리하는 예외 코드를 나타냅니다. start_pcend_pc 사이에서 예외가 발생하면 handler_pc줄로 이동하라는 뜻을 나타냅니다.

Exception 속성

메서드의 exception_table은 메서드 내에서 try catch 코드 블록을 나타냅니다. Exception 속성은 메서드에서 throw 될 수 있는 속성나냅니다. number_of_exceptions를 통해 해당 메서드가 몇 개의 예외를 던지는지 나타냅니다.

Exceptions_attribute { u2 attribute_name_index; u4 attribute_length; u2 number_of_exceptions; u2 exception_index_table[number_of_exceptions]; }

LineNumberTable 속성

자바 소스 코드의 줄 번호와 바이트코드의 줄번호 사이의 대응 관계를 설명하는 속성입니다. LineNumberTable 속성을 통해서 예외가 발생했을 때 오류를 일으킨 코드의 줄번호를 나타낼 수 있습니다.

LineNumberTable_attribute { u2 attribute_name_index; u4 attribute_length; u2 line_number_table_length; { u2 start_pc; u2 line_number; } line_number_table[line_number_table_length]; }

InnerClasses 속성

내부 클래스와 호스트 클래스 사이의 연결 관계를 나타냅니다. number_of_classes는 해당 클래스에 내부 클래스가 몇 개 있는지 나타냅니다.

InnerClasses_attribute { u2 attribute_name_index; u4 attribute_length; u2 number_of_classes; { u2 inner_class_info_index; // 내부 클래스의 심벌 (상수풀의 인덱스) u2 outer_class_info_index; // 호스트 클래스의 심벌 u2 inner_name_index; // 내부 클래스 이름 u2 inner_class_access_flags; // 내부 클래스 접근제한자 } classes[number_of_classes]; }

Signature 속성

제네릭을 지원하기 위해 추가된 속성입니다. 클래스, 필드, 메서드 테이블에서 사용할 수 있습니다. Signature속성 덕분에 리플렉션 API로 제네릭 정보를 얻을 수 있습니다.

Signature_attribute { u2 attribute_name_index; u4 attribute_length; u2 signature_index; }

Outro

이 밖에 다양한 속성들이 있습니다. 참고한 오라클 문서와 JVM 밑바닥까지 파헤치기를 참고해서 학습하면 좋을 것 같습니다.

Reference

오라클문서
JVM 밑바닥까지 파헤치기