자바 클래스 파일
Java class file인터넷 미디어 유형 | 애플리케이션/애플리케이션-vm, 애플리케이션/x-vmsd-vmx |
---|---|
개발자 | 선 마이크로시스템스 |
Java 클래스 파일은 (이 있는) 파일이다. 자바 가상 머신(JVM)에서 실행할 수 있는 자바 바이트코드를 포함하는 .classfilename 확장자). 자바 클래스 파일은 대개 자바 클래스가 포함된 자바 프로그래밍 언어 소스 파일(.java 파일)에서 자바 컴파일러에 의해 생성된다(대안으로는 다른 JVM 언어도 클래스 파일을 만드는 데 사용될 수 있다). 소스 파일에 클래스가 두 개 이상 있는 경우 각 클래스는 별도의 클래스 파일로 컴파일된다.
JVM은 많은 플랫폼에서 사용할 수 있으며, 한 플랫폼에서 컴파일된 클래스 파일은 다른 플랫폼의 JVM에서 실행될 것이다. 이것은 Java 애플리케이션을 플랫폼에 독립적으로 만든다.
역사
2006년 12월 11일, Java 사양 요청(JSR) 202에 따라 클래스 파일 형식이 수정되었다.[1]
파일 레이아웃 및 구조
섹션
Java 클래스 파일 구조에 대한 10개의 기본 섹션이 있다.
- 매직넘버: 0xCAFEBABE
- 클래스 파일 형식 버전: 클래스 파일의 부 버전 및 주 버전
- 상수 풀: 클래스에 대한 상수 풀
- 액세스 플래그: 예를 들어 클래스가 추상적인지, 정적인지 여부.
- 이 클래스: 현재 클래스의 이름
- 슈퍼 클래스: 슈퍼클래스의 이름
- 인터페이스: 클래스의 모든 인터페이스
- 필드: 클래스의 모든 필드
- 방법: 클래스의 모든 메서
- 속성: 클래스의 속성(예: 원본 파일 이름 등)
매직 넘버
클래스 파일은 다음 4바이트 헤더(16진수)로 식별된다. CA FE BA BE
(아래 표의 처음 4개 항목). 이 마법 번호의 역사는 제임스 고슬링이 팔로 알토에 있는 한 식당을 가리키며 다음과 같이 설명하였다.[2]
"우리는 세인트 미카엘 골목이라는 곳에 점심을 먹으러 가곤 했었지. 지역 전설에 따르면, 어두운 과거 깊은 곳에서, 감사하는 사자는 큰 성공을 거두기 전에 그곳에서 공연하곤 했다고 한다. 그것은 확실히 '감사의 죽음'의 장소인 꽤 펑키한 곳이었다. 제리가 죽었을 때, 그들은 심지어 작은 불교식 사당도 세웠다. 우리가 그곳에 가곤 할 때, 우리는 그곳을 카페 데드라고 불렀다. 선을 따라 어딘가에 이것이 HEX 번호라는 것이 눈에 띄었다. 파일 형식 코드를 다시 검색하고 있었는데 몇 개의 마법의 숫자가 필요했다. 하나는 영구 객체 파일이고 다른 하나는 클래스를 위한 것이었다. 오브젝트 파일 형식에는 CAFEDEDED를 사용했고, 'CAFE'(주제가 좋을 것 같았다) 뒤에 맞는 4자 육각 단어 그린핑에서 BABE를 치고 사용하기로 했다. 그 당시에는 역사의 쓰레기통 이외에는 어디에도 갈 수 없을 정도로 중요하거나 운명적으로 보이지 않았다. 그래서 CAFEBABE는 클래스 파일 형식이 되었고 CAFEDEDED는 영구 객체 형식이 되었다. 그러나 영구 객체 시설은 사라졌고, CAFEDEDEDED의 사용과 함께, 결국 RMI로 대체되었다.
일반배치
클래스 파일에는 가변 크기 항목이 포함되어 있고 포함된 파일 오프셋(또는 포인터)도 포함되어 있지 않기 때문에 일반적으로 첫 번째 바이트에서 끝까지 순차적으로 구문 분석된다. 가장 낮은 수준에서 파일 형식은 몇 가지 기본적인 데이터 유형으로 설명된다.
- u1: 서명되지 않은 8비트 정수
- u2: 빅 엔디안 바이트 순서의 부호 없는 16비트 정수
- u4: 빅 엔디안 바이트 순서의 부호 없는 32비트 정수
- 표: 일부 유형의 가변 길이 항목 배열. 표의 항목 수는 앞의 카운트 번호로 식별되지만(카운트는 u2이다) 표의 바이트 단위는 각각의 항목을 조사해야만 결정할 수 있다.
이러한 기본 유형 중 일부는 문맥에 따라 더 높은 수준의 값(현 또는 부동 소수점 등)으로 다시 해석된다. 단어 정렬의 강제성이 없기 때문에 패딩 바이트는 사용되지 않는다. 클래스 파일의 전체 레이아웃은 다음 표와 같다.
바이트 오프셋 | 사이즈를 맞추다 | 활자 또는 값 | 설명 |
---|---|---|---|
0 | 4바이트 | u1 = 0xCA 16진수 | 클래스 파일 형식을 준수하는 파일을 식별하는 데 사용되는 매직 번호(CAFEBABE) |
1 | u1 = 0xFE 16진수 | ||
2 | u1 = 0xBA 16진수 | ||
3 | u1 = 0xBE 16진수 | ||
4 | 2바이트 | u2 | 사용 중인 클래스 파일 형식의 보조 버전 번호 |
5 | |||
6 | 2바이트 | u2 | 사용 중인 클래스 파일 형식의 주 버전 번호.[3] Java SE 17 = 61(0x3D 16진수), |
7 | |||
8 | 2바이트 | u2 | 상수 풀 개수, 다음 상수 풀 테이블의 항목 수. 이 수는 실제 항목 수보다 적어도 하나 이상 많다. 다음 토론을 참조하십시오. |
9 | |||
10 | cpsize (cpsize) | 테이블 | 리터럴 번호, 문자열 및 클래스 또는 메서드에 대한 참조와 같은 항목을 포함하는 변수 크기의 상수 풀 항목 배열인 상수 풀 테이블. 1에서 시작하여 총 항목 수(풀 개수 - 1)를 포함하는 색인화됨(참고 참조). |
... | |||
... | |||
... | |||
10+10사이즈 | 2바이트 | u2 | 액세스 플래그, 비트 마스크 |
11+2사이즈 | |||
12+2사이즈 | 2바이트 | u2 | 이 클래스를 식별하고 "클래스" 유형 항목에 대한 상수 풀로 인덱싱 |
13+13사이즈 | |||
14+14 사이즈 | 2바이트 | u2 | 수퍼 클래스를 식별하고 "클래스" 유형 항목에 대한 상수 풀에 인덱싱 |
15+10사이즈 | |||
16+160사이즈 | 2바이트 | u2 | 인터페이스 수, 다음 인터페이스 테이블의 항목 수 |
17세 이상 | |||
18세 이상 | 등분하다(등분하다) | 테이블 | 인터페이스 테이블: 이 클래스에 의해 구현된 인터페이스를 설명하는 가변 길이의 상수 풀 인덱스 배열 |
... | |||
... | |||
... | |||
18+2xize+2size | 2바이트 | u2 | 필드 수, 다음 필드 테이블의 항목 수 |
19+2xize+isize | |||
20+2xize+2size | fsize(크기) | 테이블 | 필드 테이블, 가변 길이 필드 배열 각 요소는 https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.5에 정의된 field_fields 구조다. |
... | |||
... | |||
... | |||
20+2xize+isize+fsize | 2바이트 | u2 | 메서드 개수, 다음 메서드 표의 항목 수 |
21+2xize+isize+fsize | |||
22+2xize+isize+fsize | msize(음소화) | 테이블 | 메서드 표, 메서드의 가변 길이 배열 각 요소는 https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.6에 정의된 method_properties 구조다. |
... | |||
... | |||
... | |||
22+2xize+isize+fsize+msize | 2바이트 | u2 | 특성 개수, 다음 특성 테이블의 항목 수 |
23+2xize+isize+fsize+msize | |||
24+2xize+isize+fsize+msize | asize(아사이즈) | 테이블 | 특성 테이블, 가변 길이 특성 배열 각 요소는 https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7에 정의된 attribute_properties 구조다. |
... | |||
... | |||
... |
C형 프로그래밍 언어로 표현
C는 구조체 내에서 다중 가변 길이 배열을 지원하지 않기 때문에 아래 코드는 컴파일되지 않고 데모 역할만 한다.
구조상의 Class_File_Format { u4 magic_number; u2 마이너_버전; u2 major_version; u2 constant_pool_count; cp_cp 상수_풀[constant_pool_count - 1]; u2 access_message; u2 이_클래스; u2 super_class; u2 interface_count; u2 인터페이스[interface_count]; u2 fields_count; field_fields 들판[fields_count]; u2 methods_count; method_properties 방법들[methods_count]; u2 attributes_count; attribute_properties 특성[attributes_count]; }
상수 풀
상수 풀 테이블은 대부분의 리터럴 상수 값이 저장되는 곳이다. 여기에는 모든 종류의 숫자, 문자열, 식별자 이름, 클래스 및 메서드에 대한 참조, 형식 설명자 등의 값이 포함된다. 상수 풀 테이블의 특정 상수에 대한 모든 인덱스 또는 참조는 16비트(유형 u2) 번호로 제공되며, 여기서 인덱스 값 1은 테이블의 첫 번째 상수를 가리킨다(인덱스 값 0은 유효하지 않음).
파일 형식 개발 중에 이루어진 과거 선택으로 인해 상수 풀 테이블의 상수 수는 실제로 표 앞에 있는 상수 풀 수와 같지 않다. 첫째, 테이블은 (0이 아닌) 1에서 시작하여 인덱싱되지만, 카운트는 실제로 최대 인덱스 플러스 1로 해석되어야 한다.[6] 또한, 두 번째 그러한 슬롯은 직접적으로 사용되지 않는 팬텀 인덱스임에도 불구하고 두 가지 유형의 상수(길이 및 복식)가 표에서 두 개의 연속 슬롯을 차지한다.
상수 풀에 있는 각 항목(상수)의 유형은 초기 바이트 태그로 식별된다. 이 태그 뒤에 오는 바이트 수와 해당 해석은 태그 값에 따라 달라진다. 유효한 상수 유형 및 태그 값은 다음과 같다.
태그 바이트 | 추가 바이트 | 상수 설명 | 소개된 버전 |
---|---|---|---|
1 | 2+x바이트 (iii) | UTF-8(Unicode) 문자열: 16비트 숫자(유형 u2)로 접두사 앞에 붙은 문자열로 인코딩된 문자열의 바이트 수를 나타내며, 이는 문자 수와 다를 수 있다. 사용되는 인코딩은 실제로 UTF-8이 아니라 유니코드 표준 인코딩 형식을 약간 수정하는 것을 수반한다는 점에 유의한다. | 1.0.2 |
3 | 4바이트 | 정수: 빅 엔디안 형식으로 서명된 32비트 2의 보완 번호 | 1.0.2 |
4 | 4바이트 | 플로트: 32비트 단일 고정밀 IEEE 754 부동 소수점 번호 | 1.0.2 |
5 | 8바이트 | Long: 빅 엔디안 형식으로 서명된 64비트 2의 보완 번호(상수 풀 테이블에서 슬롯 두 개 사용) | 1.0.2 |
6 | 8바이트 | 이중: 64비트 이중 정밀한 IEEE 754 부동 소수점 번호(상수 풀 테이블에서 슬롯 2개 포함) | 1.0.2 |
7 | 2바이트 | 클래스 참조: 전체 클래스 이름(내부 형식)을 포함하는 UTF-8 문자열에 대한 상수 풀 내의 인덱스(big-endian) | 1.0.2 |
8 | 2바이트 | 문자열 참조: UTF-8 문자열에 대한 상수 풀 내의 인덱스(big-endian도 포함) | 1.0.2 |
9 | 4바이트 | 필드 참조: 상수 풀 내에서 두 개의 인덱스, 첫 번째 클래스 참조, 두 번째 인덱스, 이름 및 유형 설명자. (빅엔디안) | 1.0.2 |
10 | 4바이트 | 방법 참조: 상수 풀 내에서 두 개의 인덱스, 첫 번째는 클래스 참조, 두 번째는 이름 및 유형 설명자. (빅엔디안) | 1.0.2 |
11 | 4바이트 | 인터페이스 방법 참조: 상수 풀 내에서 두 개의 인덱스, 첫 번째 인덱스, 두 번째 인덱스, 이름 및 유형 설명자. (빅엔디안) | 1.0.2 |
12 | 4바이트 | 이름 및 형식 설명자: 상수 풀 내의 UTF-8 문자열로 연결되는 두 개의 인덱스, 첫 번째 인덱스(식별자)는 이름(식별자)을 나타내고 두 번째 인덱스는 특별히 인코딩된 형식 설명자. | 1.0.2 |
15 | 3바이트 | 메서드 핸들: 이 구조는 메서드 핸들을 나타내기 위해 사용되며, 형식 설명자의 1바이트에 이어 상수 풀 내의 인덱스로 구성된다.[6] | 7 |
16 | 2바이트 | 방법 유형: 이 구조는 방법 유형을 나타내는 데 사용되며 상수 풀 내의 인덱스로 구성된다.[6] | 7 |
17 | 4바이트 | 동적: 부트스트랩 방법의 호출에 의해 생성된 동적 계산 상수를 지정하는 데 사용된다.[6] | 11 |
18 | 4바이트 | 호출동적: 이것은 부트스트랩 메서드, 동적 호출 이름, 인수와 호출의 반환 유형, 그리고 선택적으로 부트스트랩 메서드에 정적 인수라고 불리는 추가 상수의 시퀀스를 지정하기 위해 불규칙한 동적 지침에 의해 사용된다.[6] | 7 |
19 | 2바이트 | 모듈: 모듈을 식별하는 데 사용된다.[6] | 9 |
20 | 2바이트 | 패키지: 모듈이 내보내거나 여는 패키지를 식별하는 데 사용된다.[6] | 9 |
정수형과 긴형의 두 가지 일체형 상수형만 있다. 부울, 바이트, 쇼트 등 상위 언어에 나타나는 기타 적분형태는 정수 상수로 표현해야 한다.
자바에서 클래스 이름은 정규화된 경우 전통적으로 "java.lang"과 같이 점으로 구분된다.오브젝트". 그러나 낮은 수준의 클래스 참조 상수 내에 "java/lang/Object"와 같이 슬래시를 대신 사용하는 내부 형식이 나타난다.
유니코드 문자열은 모니커 "UTF-8 문자열"에도 불구하고, 유사하지만 실제로 유니코드 표준에 따라 인코딩되지는 않는다. 두 가지 차이가 있다(전체적인 논의는 UTF-8 참조). 첫 번째는 코드 포인트 U+0000이 2바이트 시퀀스로 인코딩된다는 점이다. C0 80
표준 단일 바이트 인코딩 대신 (16진수) 00
. 두 번째 차이점은 보조 문자(U+10000 이상에서 BMP 외부 문자)가 UTF-8을 사용하여 직접 인코딩되는 것이 아니라 UTF-16과 유사한 대리 쌍 구성을 사용하여 인코딩되는 것이다. 이 경우 두 대리인은 각각 UTF-8로 별도로 인코딩된다. 예를 들어 U+1D11E는 6바이트 시퀀스로 인코딩된다. ED A0 B4 ED B4 9E
, 의 올바른 4바이트 UTF-8 인코딩 대신 F0 9D 84 9E
.
참고 항목
참조
- ^ JSR 202 Java 클래스 파일 사양 업데이트
- ^ 빌 범가너에게 보내는 제임스 고슬링 개인 통신
- ^ https://docs.oracle.com/javase/specs/jvms/se17/html/jvms-4.html#jvms-4.1-200-B.2
- ^ http://www.oracle.com/technetwork/java/javase/10-relnote-issues-4108729.html#Remaining
- ^ https://bugs.openjdk.java.net/browse/JDK-8148785
- ^ a b c d e f g https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.4
추가 읽기
- Tim Lindholm, Frank Yellin (1999). The Java Virtual Machine Specification (Second ed.). Prentice Hall. ISBN 0-201-43294-3. Retrieved 2008-10-13. 클래스 파일 형식을 포함하는 Java Virtual Machine의 공식 정의 문서. 책의 제1판과 제2판은 모두 온라인에서 무료로 볼 수 있고 다운로드 받을 수 있다.