자바 가상 머신 - 클래스 파일 구조

클래스 파일 구조

클래스 파일의 클래스 구조

하나의 클래스 또는 인터페이스에 해당하는 모든 클래스 파일 정의 정보,하지만 반드시 파일에 정의 된 클래스 나 인터페이스가 없습니다 (예 : 클래스는 클래스 로더에 의해 직접 발생 될 수있다 등). 클래스 파일은 기본 단위의 8 비트 바이트의 세트 이진 스트림은 상기 데이터 아이템들의 정확한 순서는 클래스 파일에서 컴팩트하게 배치되어있다. 클래스 파일 형식 의사 C 언어와 같은 두 개의 데이터 유형을 포함하여 데이터를 저장 구조에 대한 구조 : 부호와 테이블.
부호 1,2,4,8 바이트를 나타내는 U1, U2, U4, U8에 기본 데이터 타입에 속하는 부호. 도면에서, 참조 인덱스, 부호화 값 또는 스트링 구성 UTF-8에 따른 값의 수를 설명하는 데 사용될 수있다.
표 부호 번호 테이블 또는 복합 데이터 유형 "_info"끝까지 모든 테이블 습관을 구성하는 다른 데이터 항목으로 다수이다. 표는 계층 적 관계에 부합하는 데이터 구조를 설명하는 데 사용된다.

클래스 파일의 매직 번호의 버전

파일의 처음 4 바이트는 파일이 가상 파일이 클래스에 의해 허용 될 수 있는지 여부를 확인하려면 클래스 수 (매직 넘버) 마법을했다. 매직 클래스 값 파일은 다음과 같습니다 0xCAFEBABE, Java 또는이 확인되었다 "오크"의 매직 번호 (커피 아기?).
4 바이트는 클래스 파일의 버전 번호를 저장 한 후, 다섯 번째와 여섯 번째 바이트에는 마이너 버전 번호 (버전 부), (7) 제 8 주 버전 (주 버전)이다. Java 버전 번호는 45 시작에서, 그리고 큰 1.1 릴리스 주 버전 번호가 1 위로 씩 증가 후, 높은 JDK 버전은 클래스 파일의 이전 버전과 호환되지만 이후 버전을 실행할 수 없습니다.

상수 풀

메이저와 마이너 버전 번호 뒤에 시간 상수 풀은 클래스 파일들 사이 창고 자원은 다른 대부분의 데이터 유형과 관련된 항목,하지만 또한 가장 큰 프로젝트 클래스 파일 공간 중 하나를 차지한다. 상수의 수는 고정되어 있지 않기 때문에,이 상수 풀 카운트 값 (있는, constant_pool_count)의 용량을 나타내는 상수 풀 U2 데이터 형식의 입사를 방지 할 필요가있다.
(리터럴) 문자 및 기호 참조 (기호 참조) : 주요 일정 풀은 두 상수의 유형을 저장합니다. 가까운 일정한 값 최종 등등으로 선언 텍스트 문자열로 자바 언어와 일정한 수준의 개념에 리터럴. 기호 참조 컴파일러 이론은 다음과 같은 세 가지 상수를 포함하여 지역의 개념에 속한다 :

  • 클래스 및 인터페이스 완전한 이름 (정규화 된 이름)
  • 이름 및 설명 필드 (디스크립터)
  • 메소드 이름과 설명

javac의 자바 코드를 컴파일 시간은 C 또는 C ++과는 달리이 단계를 연결하지만, 가상 머신이 클래스 파일을로드 할 때 동적으로 연결했다. 가상 머신은 해당 기호가 특정 메모리 주소로 변환하는 클래스가 생성 될 때 해결되거나 실행되는 정수 풀 참조로부터 얻을 수있다, 실행됩니다.

액세스 플래그

2 바이트가 클래스 또는 인터페이스 레벨 액세스 정보의 개수를 식별하기위한 액세스 플래그 (access_flag)를 나타내는 직후 상수 풀. 포함 : 여부 공개, 추상적 여부, 최종 여부 등 클래스 또는 인터페이스.

국기 이름 플래그 값 의미
ACC_PUBLIC 0001 여부 공개
ACC_FINAL 0x0010 최종 여부
ACC_SUPER 0x0020 의미 변화가 JDK1.0.2에서 발생했기 때문에 여부 때문에 컴파일 된 클래스 후이 플래그가 참이어야합니다, 새로운 의미 invokespecial 바이트 코드 명령어의 사용을 허용하는
ACC_INTERFACE 0x0200 인터페이스 여부
ACC_ABSTRACT 0x0400 그것은 추상 클래스인지 여부
ACC_SYNTHETIC 가 0x1000 여부는 컴파일러에 의해 자동으로 생성
ACC_ANNOTATION 0x2000 인 주석 클래스 여부
ACC_ENUM 0x4000으로 열거 여부

예를 들어, ACC_PUBLIC ACC_SUPE 플래그 때문에 일반 대중 카테고리, 다른 거짓 깃발, 사실이다. 그래서 값이 access_flags : 0001가 | = 0x0021 0x0020
5 전은 정의가 표시 Java 가상 머신 사양, 세 뒤 후 1.5의 증가이다.

클래스 인덱스 및 부모 클래스 인터페이스 인덱스 세트의 인덱스

인덱스 데이터 세트 유형 U2 그룹의 인터페이스 (인터페이스)를 설정할 때, 클래스 색인 (this_class) 상위 인덱스 (super_class)은 U2의 데이터 형식이다. 액세스 플래그 뒤에 위하여.

유형 이름
U2 클래스 색인 1
U2 부모 지수 1
U2 [N] 인터페이스 색인

테이블의 필드 세트

변수를 설명하는 데 사용되는 테이블 필드 (field_info) 클래스 또는 인터페이스 내에서 선언. 이 필드는 클래스 인스턴스 변수와 클래스 변수 수준을 포함하지만, 방법 내에서 선언 된 지역 변수를 포함하지 않습니다. 플래그가 사용되는 개질제의 양은 상수 풀의 정수를 설명하는 데 사용되는 필드 이름의 형태를 나타낸다.
access_flag 의미

국기 이름 플래그 값 의미
ACC_PUBLIC 0001 여부 공개
ACC_PRIVATE 0x0002 개인 여부
ACC_PROTECTED 에 0x0004 그것은 보호 여부
ACC_STATIC 0x0008에 이 정적 여부
ACC_FINAL 0x0010 최종 여부
ACC_VOLATILE 0x0040 휘발성 여부
ACC_TRANSIENT 0x0080 과도 여부
ACC_SYNTHETIC 가 0x1000 여부는 컴파일러에 의해 자동으로 생성
ACC_ENUM 0x4000으로 열거 여부
유형 이름
U2 access_flag 1
U2 name_index 1
U2 descriptor_index 1
U2 attributes_count 1
attribute_info 속성 attributes_count

표 수집 방법

메소드 테이블 (method_info)는 클래스 또는 인터페이스 선언하는 방법을 설명한다.
휘발성 키워드 및 키워드 과도 방법이 변경 될 수 없기 때문에, 그래서 접근 플래그 테이블 방법은 ACC_VOLATILE 표지판 및 ACC_TRANSIENT 플래그 아니다. 반면, 동기화, 네이티브에 strictfp 추상적이고 키워드를 수정할 수 있습니다 방법, 액세스 플래그 테이블 방법은 ACC_NATIVE, ACC_STRICTFP 및 ACC_ABSTRACT 플래그, ACC_SYNCHRONIZED 추가합니다.

국기 이름 플래그 값 의미
ACC_PUBLIC 0001 여부 공개
ACC_PRIVATE 0x0002 개인 여부
ACC_PROTECTED 에 0x0004 그것은 보호 여부
ACC_STATIC 0x0008에 이 정적 여부
ACC_FINAL 0x0010 최종 여부
ACC_SYNCHRONIZED 0x0020 그것은 동기화 여부
ACC_BRIDGE 0x0040 여부 컴파일러를 해소하는 방법
ACC_VARARGS 0x0080 불확실한 매개 변수를 허용할지 여부
ACC_NATIVE 0x0100은 여부 출신
ACC_ABSTRACT 0x0400 추상 여부
ACC_STRICTFP 0x0800 여부의에 strictfp
ACC_SYNTHETIC 가 0x1000 여부는 컴파일러에 의해 자동으로 생성
유형 이름
U2 access_flag 1
U2 name_index 1
U2 descriptor_index 1
U2 attributes_count 1
attribute_info 속성 attributes_count

속성 시트 모음

属性表(attribute_info)之前反复出现,在Class文件、字段表、方法表都可以携带字节的属性表集合,用于描述某些场景专有信息。
顺序、长度、内容的要求不像前面那么严格。
不要求各个属性表具有严格顺序,并且只要不与已有属性名重复,任何人 实现的编译器都可以向属性表中写入自己定义的属性信息,Java虚拟机运行时会忽略掉它不 认识的属性。

属性名称 使用位置 含义
Code 方法表 Java代码编译成的字节码指令
ConstantValue 字段表 final关键字定义的常量值
Deprecated 类、方法表、字段表 声明为deprecated的方法和字段
Exceptions 方法表 方法抛出的异常
EnclosingMethod 类文件 仅当一个类为局部类或者匿名类才有这个属性,用于标识这个类所在的外围方法

...

属性表结构:

类型 名称 数量
u2 attribute_name_index 1
u4 attribute_length 1
u1 info attribute_length

完整结构描述

表用于描述有层次关系的符合结构的数据,整个Class文件本质上就是一张表,其构成成分就是如下的数据项:

数据类型 名称 数量
u2 attribute_name_index 1
u4 attribute_length 1
u2 max_stack 1
u2 max_locals 1
u4 code_length 1
u1 code code_length
u2 exception_table_length 1
exception_info exception_table exception_table_length
u2 attribute_count 1
attribute_info attributes attribute_count

实例

为了能够更好的理解,我们拿一个实际的类文件来分析一下。

源码

package com.software5000.base.jsql;

public class TestClass {
    public String strField;

    public int intField;

    public String getStrField() {
        return strField;
    }

    public void setStrField(String strField) {
        this.strField = strField;
    }

    public int getIntField() {
        return intField;
    }

    public void setIntField(int intField) {
        this.intField = intField;
    }
}

这是一个很简单的测试类,两个属性,以及对应的getter/setter方法。

Class文件

Class文件

分析

针对类文件以及前面的概念对比分析

魔数、Class版本

CAFEBABE - 魔数
00000034 - 版本 52 :jdk 1.8

常量池长度

0020 - 32-1 长度31个常量项

常量池内容

01——
0A tag表示 constant_methodref_info
0005 index no. 5 contant_class_info
001B index no. 27 constant_nameandtype

02——
09 tag constant_fieldref_info
0004 index no.4 constant_class_info
001C index no.28 constatn_nameandtype

03——
09 tag constant_fieldref_info
0004 index no.4 constant_class_info
001D index no.29 constatn_nameandtype

04——
07 tag constant_class_info
001E index no.30

05——
07 tag constant_class_info
001F index no.31

06——
01 tag constant_utf8_info
0008 length 8 byte
7374 7246 6965 6C64 strField

07——
01 tag constant_utf8_info
0012 length 18 byte
4C6A 6176 612F 6C61 6E67 2F53 7472 696E 673B Ljava/lang/String;

08——
01 tag constant_utf8_info
0008 length 8 byte
696E 7446 6965 6C64 intField

09——
01 tag constant_utf8_info
0001 length 1 byte
49 I

10——
01 tag constant_utf8_info
0006 length 6 byte
3C69 6E69 743E

11——
01 tag constant_utf8_info
0003 length 3 byte
2829 56 ()V

12——
01 tag constant_utf8_info
0004 length 4 byte
436F 6465 Code

13——
01 tag constant_utf8_info
000F length 15 byte
4C69 6E65 4E75 6D62 6572 5461 626C 65 LineNumberTable

14——
01 tag constant_utf8_info
0012 length 18 byte
4C6F 6361 6C56 6172 6961 626C 6554 6162 6C65 LocalVariableTable

15——
01 tag constant_utf8_info
0004 length 4 byte
7468 6973 this

16——
01 tag constant_utf8_info
0026 length 38 byte
4C63 6F6D 2F73 6F66 7477 6172 6535 3030 302F 6261 7365 2F6A 7371 6C2F 5465 7374 436C 6173 733B Lcom/software5000/base/jsql/TestClass;

17——
01 tag constant_utf8_info
000B length 11 byte
67 6574 5374 7246 6965 6C64 getStrField

18——
01 tag constant_utf8_info
0014 length 20 byte
2829 4C6A 6176 612F 6C61 6E67 2F53 7472 696E 673B ()Ljava/lang/String;

19——
01 tag constant_utf8_info
000B length 11 byte
7365 7453 7472 4669 656C 64 setStrField

20——
01 tag constant_utf8_info
0015 length 21 byte
284C 6A61 7661 2F6C 616E 672F 5374 7269 6E67 3B29 56 (Ljava/lang/String;)V

21——
01 tag constant_utf8_info
000B length 11 byte
6765 7449 6E74 4669 656C 64 getIntField

22——
01 tag constant_utf8_info
0003 length 3 byte
2829 49 ()I

23——
01 tag constant_utf8_info
000B length 11 byte
7365 7449 6E74 4669 656C 64 setIntField

24——
01 tag constant_utf8_info
0004 length 4 byte
2849 2956 (I)V

25——
01 tag constant_utf8_info
000A length 10 byte
536F 7572 6365 4669 6C65 SourceFile

26——
01 tag constant_utf8_info
000E length 14 byte
5465 7374 436C 6173 732E 6A61 7661 TestClass.java

27——
0C tag constant_Name-andtype-info
000A index no.10
000B index no.11

28——
0C tag constant_Name-andtype-info
0006 index no.6
0007 index no.7

29——
0C tag constant_Name-andtype-info
0008 index no.8
0009 index no.9

30——
01 tag constant_utf8_info
0024 length 36 byte
5636F 6D2F 736F 6674 7761 7265 3530 3030 2F62 6173 652F 6A73 716C 2F54 6573 7443 6C61 7373 com/software5000/base/jsql/TestClass

31——
01 tag constant_utf8_info
0010 length 16 byte
6A61 7661 2F6C 616E 672F 4F62 6A65 6374 java/lang/Object

访问标志

0021 访问标志 (ACC_PUBLIC,ACC_SUPER两个标志位为真)

类索引、父类索引、接口索引

0004 类索引 no.4
0005 父类索引 no.5
0000 接口索引集合 0

字段表集合

0002 fields_counts 2个字段表数据

No.1 field
0001 access_flag public
0006 index no.6 name_index
0007 index no.7 descriptor_index
0000 attributes_count

No.2 field
0001 access_flag public
0008 index no.8 name_index
0009 index no.9 descriptor_index
0000 attributes_count

方法表集合

0005 methods_count 5个方法

No.1 method
0001 access_flag public
000A index no.10 name_index
000B index no.11 descriptor_index ()V
0001 attributes_count 1个
000C attributes_info LineNumberTable

剩余的待进一步补充。。。

总结

Class文件的结构理解,说实话对于编码或者性能优化等方面没有什么特别大的帮助,但是能够帮我们更好的理解Java及其设计的思想。我们从Class文件的结构设计中也能够学习到一些模式,这些东西可能会在后续的研发过程提供一些解决问题或者设计方案的思路。
这才是最重要的。

추천

출처www.cnblogs.com/pluto4596/p/11870986.html