java.class文件结构学习
2017-09-01 10:07
295 查看
1.
u1,u2,u3,u4 表示 1字节,2字节,3字节,4字节
class文件
类型 名称 数量
u4 magic 1
u2 minor_version 1
u2 major_version 1
u2 constant_pool_count 1
cp_info constant_pool constant_pool_count - 1
u2 access_flags 1 (access_flags 描述的是当前类(或者接口)的访问修饰符, 如public, private等,还有该类是类,接口还是枚举等)
u2 this_class 1 (当前类的信息,索引class_index ->CONSTANT_Class_info)
u2 super_class 1 (父类的信息,索引class_index ->CONSTANT_Class_info)
u2 interfaces_count 1 (当前类接口数量)
face_info interfaces interfaces_count (每一个接口占u2块,每一块有个索引然后指向CONSTANT_Class_info)
u2 fields_count 1 (当前类定义的字段(变量)的个数,但不包括从父类继承的字段)
field_info fields fields_count (下面有描述)
u2 methods_count 1 (当前类中定义的方法个数,不包括从父类继承的方法)
method_info methods methods_count (对方法的描述)
u2 attribute_count 1 (属性长度)
attribute_info attributes attributes_count (属性数组)
0-3字节(判断该文件是否是虚拟机可接收的Class文件,就好像PE文件开头有个MZ)
4-7字节(版本号)
接下来为常量池中数据项
CONSTANT_Utf8_info ( 程序中的字符串常量, 类型的全限定名, 方法和字段的名称, 方法和字段的描述符, 属性相关字符串)
格式:
tag
length
bytes
例如
1
5
h
e
l
l
o
CONSTANT_NameAndType(表示了一个方法或一个字段)
tag
name_index(它指向常量池中的一个CONSTANT_Utf8_info, 这个CONSTANT_Utf8_info中存储的就是方法或字段的名称)
descriptor_index(它指向常量池中的一个CONSTANT_Utf8_info, 这个CONSTANT_Utf8_info中存储的就是方法或字段的描述符)
#5 = Utf8 age
#6 = Utf8 I
#19 = NameAndType #5:#6 // age:I
则有
tag 19
name 5
descriptor_index 6
CONSTANT_Integer_info(它存储的是源文件中出现的int型数据的值)
tag(3)
bytes(值)
CONSTANT_String_info(它的作用是存储文字字符串)
tag(8)
string_index(链接到CONSTANT_Utf8_info)
CONSTANT_Class_info(存储类信息)
tag(7)
name_index(CONSTANT_Utf8_info())
CONSTANT_Fieldref_info(对一个字段(变量等)的符号引用, 这个符号引用包括两部分, 一部分是该字段所在的类, 另一部分是该字段的字段名和描述符)
tag
class_index(CONSTANT_Class_info)
name_and_type_index(CONSTANT_NameAndType_info)
CONSTANT_Methodref_info(一个类中方法的符号引用)
tag(10)
class_index(CONSTANT_Class_info)
name_and_type_index(CONSTANT_NameAndType_info)
CONSTANT_InterfaceMethodref_info(接口,都差不多)
fields
field_info结构如下:
access_flags(字段的访问标志,public,private,protected,static,final,volatile,transient等)
name_index (常量池的索引,名称,CONSTANT_Utf8_info)
descriptor_index(指向常量池的索引,描述)
attributes_count(表示这个字段有几个属性)
attributes(各个属性数组,属性一般有三种,ConstantValue, Deprecated, Synthetic)
methods
method_info结构如下:
access_flags(字段的访问标志,public,private,protected,static,final,volatile,transient等)
name_index (常量池的索引,名称,CONSTANT_Utf8_info)
descriptor_index(指向常量池的索引,描述)
attributes_count(表示这个字段有几个属性)
attributes(各个属性数组,属性一般有四种,Code, Deprecated, Exceptions 和Synthetic)
attributes
attribute结构:
attribute_name_index(2字节)(指向一个CONSTANT_Utf8_info,存放当前属性名)
attribute_length(4字节)(当前属性的长度,也就是info的长度)
info
info:
sourcefile_index:(指向一个常量池索引)
类型有:
SourceFile(描述了该类是从哪个源文件中编译来的, 注意, 描述的是源文件, 而不是类, 一个源文件中可以存在多个类。)
InnerClasses 描述的是内部类和外围类的关系
Synthetic表示这个字段, 方法或类不是有用户代码生成的(即不存在与源文件中), 而是由编译器自动添加的。(内部类啥的)
ConstantValue(静态字段才可以有ConstantValue属性)
Deprecated(源文件中出现的@deprecated注解,表示类过时等等)
Exceptions(描述的是方法声明的可能会抛出的异常)
Code(最重要的属性,存放方法的字节码指令(代码), 除此之外还存放了和操作数栈,局部变量相关的信息)
结构:
attibute_name_index
attribute_length
max_stack (当前方法被执行引擎执行的时候, 在栈帧中需要分配的操作数栈的大小)
max_locals (当前方法被执行引擎执行的时候, 在栈帧中需要分配的局部表量表的大小)
code_length
code (字节指令,代码)
exception_table_length
exception_table (异常表,对方法体中try-catch_finally的描述)
attributes_count
attributes (其他属性)
LineNumberTable属性存在于Code属性中:
它建立了字节码偏移量到源代码行号之间的联系(这个可能就是jvm计数器相关,返回行号)
LocalVariableTable属性存在于Code属性中:
建立了方法中的局部变量与源代码中的局部变量之间的对应关系,(所谓的局部变量表)
u1,u2,u3,u4 表示 1字节,2字节,3字节,4字节
class文件
类型 名称 数量
u4 magic 1
u2 minor_version 1
u2 major_version 1
u2 constant_pool_count 1
cp_info constant_pool constant_pool_count - 1
u2 access_flags 1 (access_flags 描述的是当前类(或者接口)的访问修饰符, 如public, private等,还有该类是类,接口还是枚举等)
u2 this_class 1 (当前类的信息,索引class_index ->CONSTANT_Class_info)
u2 super_class 1 (父类的信息,索引class_index ->CONSTANT_Class_info)
u2 interfaces_count 1 (当前类接口数量)
face_info interfaces interfaces_count (每一个接口占u2块,每一块有个索引然后指向CONSTANT_Class_info)
u2 fields_count 1 (当前类定义的字段(变量)的个数,但不包括从父类继承的字段)
field_info fields fields_count (下面有描述)
u2 methods_count 1 (当前类中定义的方法个数,不包括从父类继承的方法)
method_info methods methods_count (对方法的描述)
u2 attribute_count 1 (属性长度)
attribute_info attributes attributes_count (属性数组)
0-3字节(判断该文件是否是虚拟机可接收的Class文件,就好像PE文件开头有个MZ)
4-7字节(版本号)
接下来为常量池中数据项
CONSTANT_Utf8_info ( 程序中的字符串常量, 类型的全限定名, 方法和字段的名称, 方法和字段的描述符, 属性相关字符串)
格式:
tag
length
bytes
例如
1
5
h
e
l
l
o
CONSTANT_NameAndType(表示了一个方法或一个字段)
tag
name_index(它指向常量池中的一个CONSTANT_Utf8_info, 这个CONSTANT_Utf8_info中存储的就是方法或字段的名称)
descriptor_index(它指向常量池中的一个CONSTANT_Utf8_info, 这个CONSTANT_Utf8_info中存储的就是方法或字段的描述符)
#5 = Utf8 age
#6 = Utf8 I
#19 = NameAndType #5:#6 // age:I
则有
tag 19
name 5
descriptor_index 6
CONSTANT_Integer_info(它存储的是源文件中出现的int型数据的值)
tag(3)
bytes(值)
CONSTANT_String_info(它的作用是存储文字字符串)
tag(8)
string_index(链接到CONSTANT_Utf8_info)
CONSTANT_Class_info(存储类信息)
tag(7)
name_index(CONSTANT_Utf8_info())
CONSTANT_Fieldref_info(对一个字段(变量等)的符号引用, 这个符号引用包括两部分, 一部分是该字段所在的类, 另一部分是该字段的字段名和描述符)
tag
class_index(CONSTANT_Class_info)
name_and_type_index(CONSTANT_NameAndType_info)
CONSTANT_Methodref_info(一个类中方法的符号引用)
tag(10)
class_index(CONSTANT_Class_info)
name_and_type_index(CONSTANT_NameAndType_info)
CONSTANT_InterfaceMethodref_info(接口,都差不多)
fields
field_info结构如下:
access_flags(字段的访问标志,public,private,protected,static,final,volatile,transient等)
name_index (常量池的索引,名称,CONSTANT_Utf8_info)
descriptor_index(指向常量池的索引,描述)
attributes_count(表示这个字段有几个属性)
attributes(各个属性数组,属性一般有三种,ConstantValue, Deprecated, Synthetic)
methods
method_info结构如下:
access_flags(字段的访问标志,public,private,protected,static,final,volatile,transient等)
name_index (常量池的索引,名称,CONSTANT_Utf8_info)
descriptor_index(指向常量池的索引,描述)
attributes_count(表示这个字段有几个属性)
attributes(各个属性数组,属性一般有四种,Code, Deprecated, Exceptions 和Synthetic)
attributes
attribute结构:
attribute_name_index(2字节)(指向一个CONSTANT_Utf8_info,存放当前属性名)
attribute_length(4字节)(当前属性的长度,也就是info的长度)
info
info:
sourcefile_index:(指向一个常量池索引)
类型有:
SourceFile(描述了该类是从哪个源文件中编译来的, 注意, 描述的是源文件, 而不是类, 一个源文件中可以存在多个类。)
InnerClasses 描述的是内部类和外围类的关系
Synthetic表示这个字段, 方法或类不是有用户代码生成的(即不存在与源文件中), 而是由编译器自动添加的。(内部类啥的)
ConstantValue(静态字段才可以有ConstantValue属性)
Deprecated(源文件中出现的@deprecated注解,表示类过时等等)
Exceptions(描述的是方法声明的可能会抛出的异常)
Code(最重要的属性,存放方法的字节码指令(代码), 除此之外还存放了和操作数栈,局部变量相关的信息)
结构:
attibute_name_index
attribute_length
max_stack (当前方法被执行引擎执行的时候, 在栈帧中需要分配的操作数栈的大小)
max_locals (当前方法被执行引擎执行的时候, 在栈帧中需要分配的局部表量表的大小)
code_length
code (字节指令,代码)
exception_table_length
exception_table (异常表,对方法体中try-catch_finally的描述)
attributes_count
attributes (其他属性)
LineNumberTable属性存在于Code属性中:
它建立了字节码偏移量到源代码行号之间的联系(这个可能就是jvm计数器相关,返回行号)
LocalVariableTable属性存在于Code属性中:
建立了方法中的局部变量与源代码中的局部变量之间的对应关系,(所谓的局部变量表)
相关文章推荐
- JVM学习序列之一:Java Class文件结构分析
- JVM学习序列之一:Java Class文件结构分析
- java Class文件内部结构解析过程详解
- 实例分析 Java Class 的文件结构
- java学习笔记 使用递归 将文件目录树形结构输出,递归删除目录 文件夹。
- 实例分析Java Class的文件结构
- Java的class文件结构
- 实例分析Java Class的文件结构
- 通过阅读、分析和翻译二进制格式的Java Class文件学习Java Class的技术
- java class文件结构(二)
- Java 编译产生的class文件 格式 结构图
- java中的class文件结构
- Java 批量反编译class文件,并保持目录结构
- Java的class文件结构
- Java Class文件结构
- java虚拟机学习笔记——java class文件的内容(第六章)
- Java的字节码class文件结构
- 【JAVA学习】读取文件getClassLoader().getResourceAsStream("xxx")
- 实例分析Java Class的文件结构
- java 的*.class文件结构