저는 현재 ClassAnalyzer
이라는 개인 프로젝트를 작성 중입니다. ClassAnalyzer
의 목적은 <span class="wp_keywordlink">Java Class</span>
파일의 디자인과 구조에 대한 깊은 이해를 제공하는 것입니다. 본체프레임워크와 기본 기능은 완성되었으며, 향후 일부 세부 기능이 추가될 예정입니다. 사실 JDK
은 이미 javap
파일을 디컴파일하는 명령줄 도구 Class
를 제공하지만 이 글에서는 파서 구현에 대한 내 생각을 명확히 할 것입니다.
은 클래스 또는 인터페이스 정보를 전달하는 역할을 합니다. 각 Class
파일은 클래스를 완전히 정의합니다. Java
프로그램을 "한 번 작성하면 어디서나 실행"할 수 있도록 Java 가상 머신 사양에는 Class
파일에 대한 엄격한 규정이 있습니다. Class
파일을 구성하는 기본 데이터 단위는 바이트입니다. 이로 인해 전체 Class
파일에 저장된 내용은 단일 바이트로 표현할 수 없는 거의 모든 데이터가 됩니다. . 데이터는 여러 연속 바이트로 표시됩니다.
Java
가상 머신 사양에 따르면 Class
파일은 C
언어 구조와 유사한 의사 구조를 사용하여 데이터를 저장합니다. 이 의사에는 두 가지 데이터 유형만 있습니다. -구조: 부호 없는 합계 테이블입니다. Java
가상 머신 사양은 u1
바이트, u2
바이트, u4
바이트 및 u8
을 각각 나타내는 1
, 2
, 4
및 8
을 정의합니다. . 부호 없는 숫자는 숫자, 색인참조, 수량 값 또는 문자열을 설명하는 데 사용할 수 있습니다. 테이블은 여러 개의 부호 없는 숫자 또는 기타 테이블을 데이터 항목으로 구성한 데이터 유형입니다. 테이블은 계층적 관계로 구조화된 데이터를 설명하는 데 사용되므로 전체 Class
파일은 기본적으로 테이블입니다. ClassAnalyzer
에서 u1
, u2
, u4
, u8
는 각각 byte
, short
, int
, long
에 해당하며, Class
파일에 대해서는 다음과 같이 설명한다. 🎜> 친절해요. Java
public class ClassFile { public U4 magic; // magic public U2 minorVersion; // minor_version public U2 majorVersion; // major_version public U2 constantPoolCount; // constant_pool_count public ConstantPoolInfo[] cpInfo; // cp_info public U2 accessFlags; // access_flags public U2 thisClass; // this_class public U2 superClass; // super_class public U2 interfacesCount; // interfaces_count public U2[] interfaces; // interfaces public U2 fieldsCount; // fields_count public FieldInfo[] fields; // fields public U2 methodsCount; // methods_count public MethodInfo[] methods; // methods public U2 attributesCount; // attributes_count public BasicAttributeInfo[] attributes; // attributes }매직 넘버,
Class
의 다양한 데이터 항목을 구문 분석하는 방법 , 부모 클래스 인덱스, 각 Class
파일에서 고정된 바이트 수를 차지하며 구문 분석 시 해당 바이트 수만 읽어야 합니다. 또한 유연하게 처리해야 하는 주요 부분으로는 Class
부분인 상수 풀, 필드 테이블 수집, 메소드 테이블 수집, 속성 테이블 수집이 있습니다. 필드와 메소드는 고유한 속성을 가질 수 있으며 4
자체에도 해당 속성이 있으므로 필드 테이블 컬렉션과 메소드 테이블 컬렉션을 구문 분석하면 속성 테이블도 구문 분석됩니다. Class
파일의 데이터 중 많은 부분을 차지하며 숫자 및 문자열 상수, 클래스 이름, 인터페이스 이름, 필드 이름, 메소드 이름 등을 포함한 모든 상수 정보를 저장하는 데 사용됩니다. . Class
가상 머신 사양은 여러 상수 유형을 정의하며, 각 상수 유형은 고유한 구조를 갖습니다. 상수 풀 자체는 테이블이며, 이를 구문 분석할 때 주의해야 할 몇 가지 사항이 있습니다. Java
유형의 태그로 식별됩니다. u1
)는 실제 constantPoolCount
보다 큽니다. 예를 들어 1
가 constantPoolCount
과 같은 경우에는 항목 상수가 있습니다. 47
46
가 1
과 같으면 상수 풀의 인덱스 범위는 . 디자이너는 "상수 풀 항목을 참조하지 않음"을 표현하기 위해 constantPoolCount
항목을 비워 두었습니다. 47
1~46
0
, CONSTANT_Utf8_info
유형의 u1
을 포함하며 tag
유형의 u2
개 조각으로 구성됩니다. length
, 이 length
바이트의 연속 데이터는 u1
(bytes
을 사용하여 인코딩된 문자열입니다. length
은 MUTF-8
과 호환되지 않습니다. 두 가지 주요 차이점이 있습니다. 첫째, Modified UTF-8)
문자는 MUTF-8
바이트(UTF-8
및 null
)로 인코딩됩니다. 둘째, 보조 문자는 2
에 따라 서로게이트 쌍으로 분할되고 별도로 인코딩됩니다(변형 UTF-8). >
属性表用于描述某些场景专有的信息,Class
文件、字段表和方法表都有相应的属性表集合。Java
虚拟机规范定义了多种属性,ClassAnalyzer
目前实现了对常用属性的解析。和常量类型的数据项不同,属性并没有一个tag
来标识属性的类型,但是每个属性都包含有一个u2
类型的attribute_name_index
,attribute_name_index
指向常量池中的一个CONSTANT_Utf8_info
类型的常量,该常量包含着属性的名称。在解析属性时,ClassAnalyzer
正是通过attribute_name_index
指向的常量对应的属性名称来得知属性的类型。
字段表用于描述类或者接口中声明的变量,字段包括类级变量以及实例级变量。字段表的结构包含一个u2
类型的access_flags
、一个u2
类型的name_index
、一个u2
类型的descriptor_index
、一个u2
类型的attributes_count
和attributes_count
个attribute_info
类型的attributes
。我们已经介绍了属性表的解析,attributes
的解析方式与属性表的解析方式一致。
Class
的文件方法表采用了和字段表相同的存储格式,只是access_flags
对应的含义有所不同。方法表包含着一个重要的属性:Code
属性。Code
属性存储了Java
代码编译成的字节码指令,在ClassAnalyzer
中,Code
对应的Java
类如下所示(仅列出了类属性)。
public class Code extends BasicAttributeInfo { private short maxStack; private short maxLocals; private long codeLength; private byte[] code; private short exceptionTableLength; private ExceptionInfo[] exceptionTable; private short attributesCount; private BasicAttributeInfo[] attributes; ... private class ExceptionInfo { public short startPc; public short endPc; public short handlerPc; public short catchType; ... } }
在Code
属性中,codeLength
和code
分别用于存储字节码长度和字节码指令,每条指令即一个字节(u1
类型)。在虚拟机执行时,通过读取code
中的一个个字节码,并将字节码翻译成相应的指令。另外,虽然codeLength
是一个u4
类型的值,但是实际上一个方法不允许超过65535
条字节码指令。
ClassAnalyzer
的源码已放在了GitHub上。在ClassAnalyzer
的README中,我以一个类的Class
文件为例,对该Class
文件的每个字节进行了分析,希望对大家的理解有所帮助。
위 내용은 Java 클래스 파서를 구현하기 위한 강력한 코드 공유의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!