max_stack:操作数栈深度最大值,在方法执行的不论什么时刻,操作数栈深度都不会超过这个值。虚拟机执行时依据这个值来分配栈帧的操作数栈深度
max_locals:局部变量表所需存储空间,单位为Slot(參见备注四)。
并非全部局部变量占用的Slot之和,当一个局部变量的生命周期结束后。其所占用的Slot将分配给其他依旧存活的局部变量使用。按此方式计算出方法执行时局部变量表所需的存储空间
code_length和code:用来存放Java源程序编译后生成的字节码指令。code_length代表字节码长度,code是用于存储字节码指令的一系列字节流。
每个指令是一个u1类型的单字节,当虚拟机读到code中的一个字节码(一个字节能表示256种指令,Java虚拟机规范定义了当中约200个编码相应的指令)。就能够推断出该字节码代表的指令。指令后面是否带有參数,參数该怎样解释。尽管code_length占4个字节,可是Java虚拟机规范中限制一个方法不能超过65535条字节码指令。假设超过。Javac将拒绝编译
ConstantValue属性:通知虚拟机自己主动为静态变量赋值,仅仅有被statickeyword修饰的变量(类变量)才干够使用这项属性。
其结构例如以下:
类型
名称
数量
u2
attribute_name_index
1
u4
attribute_length
1
u2
constantvalue_index
1
能够看出ConstantValue属性是一个定长属性,当中attribute_length的值固定为0x00000002,constantvalue_index为一常量池字面量类型常量索引(Class文件格式的常量类型中仅仅有与基本类型和字符串类型相相应的字面量常量,所以ConstantValue属性仅仅支持基本类型和字符串类型)
对非static类型变量(实例变量。如:int a = 123;)的赋值是在实例构造器方法中进行的
对类变量(如:static int a = 123;)的赋值有2种选择,在类构造器方法中或使用ConstantValue属性。当前Javac编译器的选择是:假设变量同一时候被static和final修饰(虚拟机规范仅仅要求有ConstantValue属性的字段必须设置ACC_STATIC标志,对finalkeyword的要求是Javac编译器自己增加的要求),而且该变量的数据类型为基本类型或字符串类型。就生成ConstantValue属性进行初始化;否则在类构造器方法中进行初始化
Exceptions属性:列举出方法中可能抛出的受查异常(即方法描写叙述时throwskeyword后列出的异常),与Code属性平级,与Code属性包括的异常表不同,其结构为:
类型
名称
数量
u2
attribute_name_index
1
u4
attribute_length
1
u2
number_of_exceptions
1
u2
exception_index_table
number_of_exceptions
number_of_exceptions表示可能抛出number_of_exceptions种受查异常
exception_index_table为异常索引集合,一组u2类型exception_index的集合,每个exception_index为一个指向常量池中一CONSTANT_Class_info型常量的索引,代表该受查异常的类型
InnerClasses属性:该属性用于记录内部类和宿主类之间的关系。
假设一个类中定义了内部类。编译器将会为这个类与这个类包括的内部类生成InnerClasses属性,结构为:
类型
名称
数量
u2
attribute_name_index
1
u4
attribute_length
1
u2
number_of_classes
1
inner_classes_info
inner_classes
number_of_classes
inner_classes为内部类表集合。一组内部类表类型数据的集合,number_of_classes即为集合中内部类表类型数据的个数
每个内部类的信息都由一个inner_classes_info表来描写叙述,inner_classes_info表结构例如以下:
类型
名称
数量
u2
inner_class_info_index
1
u2
outer_class_info_index
1
u2
inner_name_index
1
u2
inner_name_access_flags
1
inner_class_info_index和outer_class_info_index指向常量池中CONSTANT_Class_info类型常量索引,该CONSTANT_Class_info类型常量指向常量池中CONSTANT_Utf8_info类型常量。分别为内部类的全限定名和宿主类的全限定名
inner_name_index指向常量池中CONSTANT_Utf8_info类型常量的索引。为内部类名称,假设为匿名内部类。则该值为0
inner_name_access_flags类似于access_flags。是内部类的訪问标志
标志名称
标志值
含义
ACC_PUBLIC
0x0001
内部类是否为public
ACC_PRIVATE
0x0002
内部类是否为private
ACC_PROTECTED
0x0004
内部类是否为protected
ACC_STATIC
0x0008
内部类是否为static
ACC_FINAL
0x0010
内部类是否为final
ACC_INTERFACE
0x0020
内部类是否为一个接口
ACC_ABSTRACT
0x0400
内部类是否为abstract
ACC_SYNTHETIC
0x1000
内部类是否为编译器自己主动产生
ACC_ANNOTATION
0x4000
内部类是否是一个注解
ACC_ENUM
0x4000
内部类是否是一个枚举
LineNumberTale属性:用于描写叙述Java源代码的行号与字节码行号之间的相应关系,非执行时必需属性。会默认生成至Class文件里,能够使用Javac的-g:none或-g:lines关闭或要求生成该项属性信息,其结构例如以下:
类型
名称
数量
u2
attribute_name_index
1
u4
attribute_length
1
u2
line_number_table_length
1
line_number_info
line_number_table
line_number_table_length
line_number_table是一组line_number_info类型数据的集合。其所包括的line_number_info类型数据的数量为line_number_table_length。line_number_info结构例如以下:
类型
名称
数量
说明
u2
start_pc
1
字节码行号
u2
line_number
1
Java源代码行号
不生成该属性的最大影响是:1,抛出异常时,堆栈将不会显示出错的行号。2。调试程序时无法依照源代码设置断点
LocalVariableTable属性:用于描写叙述栈帧中局部变量表中的变量与Java源代码中定义的变量之间的关系。非执行时必需属性,默认不会生成至Class文件里,能够使用Javac的-g:none或-g:vars关闭或要求生成该项属性信息。其结构例如以下:
类型
名称
数量
u2
attribute_name_index
1
u4
attribute_length
1
u2
local_variable_table_length
1
local_variable_info
local_variable_table
local_variable_table_length
local_variable_table是一组local_variable_info类型数据的集合,其所包括的local_variable_info类型数据的数量为local_variable_table_length,local_variable_info结构例如以下:
类型
名称
数量
说明
u2
start_pc
1
局部变量的生命周期開始的字节码偏移量
u2
length
1
局部变量作用范围覆盖的长度
u2
name_index
1
指向常量池中CONSTANT_Utf8_info类型常量的索引,局部变量名称
u2
descriptor_index
1
指向常量池中CONSTANT_Utf8_info类型常量的索引。局部变量描写叙述符
u2
index
1
局部变量在栈帧局部变量表中Slot的位置,假设这个变量的数据类型为64位类型(long或double),
它占用的Slot为index和index+1这2个位置
start_pc + length即为该局部变量在字节码中的作用域范围
不生成该属性的最大影响是:1,当其它人引用这种方法时,全部的參数名称都将丢失,IDE可能会使用诸如arg0、arg1之类的占位符取代原有的參数名称,对代码执行无影响,会给代码的编写带来不便。2,调试时调试器无法依据參数名称从执行上下文中获取參数值
SourceFile属性:用于记录生成这个Class文件的源代码文件名,为可选项,能够使用Javac的-g:none或-g:source关闭或要求生成该项属性信息,其结构例如以下:
型
名称
数量
u2
attribute_name_index
1
u4
attribute_length
1
u2
sourcefile_index
1
能够看出SourceFile属性是一个定长属性,sourcefile_index是指向常量池中一CONSTANT_Utf8_info类型常量的索引。常量的值为源代码文件的文件名称
对大多数文件,类名和文件名称是一致的,少数特殊类除外(如:内部类)。此时假设不生成这项属性。当抛出异常时,堆栈中将不会显示出错误代码所属的文件名称
Deprecated属性和Synthetic属性:这两个属性都属于标志类型的布尔属性。仅仅存在有和没有的差别。没有属性值的概念
Deprecated属性表示某个类、字段或方法已经被程序作者定为不再推荐使用。可在代码中使用@Deprecated注解进行设置
Synthetic属性表示该字段或方法不是由Java源代码直接产生的,而是由编译器自行加入的(当然也可设置訪问标志中的ACC_SYNTHETIC标志。全部由非用户代码产生的类、方法和字段都应当至少设置Synthetic属性和ACC_SYNTHETIC标志位中的一项,唯一的例外是实例构造器和类构造器方法)
这两项属性的结构为(当然attribute_length的值必须为0x00000000):
类型
名称
数量
u2
attribute_name_index
1
u4
attribute_length
1
起始2位为0x0001。说明有一个类属性。接下来2位为属性的名称,0x0014,指向常量池中第20个常量:SourceFile。
接下来4位为0x00000002,说明属性体长度为2字节。最后2个字节为0x0014。指向常量池中第21个常量:Test.java。即这个Class文件的源代码文件名称为Test.java
PS:
1,全限定名:将类全名中的“.”替换为“/”,为了保证多个连续的全限定名之间不产生混淆,在最后加上“;”表示全限定名结束。
比如:"com.test.Test"类的全限定名为"com/test/Test;"
2,简单名称:没有类型和參数修饰的方法或字段名称。比如:"public void add(int a,int b){...}"该方法的简单名称为"add","int a = 123;"该字段的简单名称为"a"
3。描写叙述符:描写叙述字段的数据类型、方法的參数列表(包含数量、类型和顺序)和返回值。依据描写叙述符规则,基本数据类型和代表无返回值的void类型都用一个大写字符表示,而对象类型则用字符L加对象全限定名表示
标识字符
含义
B
基本类型byte
C
基本类型char
D
基本类型double
F
基本类型float
I
基本类型int
J
基本类型long
S
基本类型short
Z
基本类型boolean
V
特殊类型void
L
对象类型,如:Ljava/lang/Object;
对于数组类型,每一维将使用一个前置的“[”字符来描写叙述,如:"int[]"将被记录为"[I","String[][]"将被记录为"[[Ljava/lang/String;"
用描写叙述符描写叙述方法时,依照先參数列表,后返回值的顺序描写叙述,參数列表依照參数的严格顺序放在一组"()"之内。如:方法"String getAll(int id,String name)"的描写叙述符为"(I,Ljava/lang/String;)Ljava/lang/String;"
4,Slot。虚拟机为局部变量分配内存所使用的最小单位,长度不超过32位的数据类型占用1个Slot,64位的数据类型(long和double)占用2个Slot