Java教程

Java字节码文件(.class)结构略解3-属性表

本文主要是介绍Java字节码文件(.class)结构略解3-属性表,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

属性表可选项

​ 属性表的一个集合作为.class文件是最后一项,其格式较为宽松,首先是各个属性表的顺序可以是任意的,其次是任何人都可以设计自己的属性表,只要不与现有的属性表冲突。

​ 字典时间,28种属性表:

属性名称使用位置含义
Code方法表Java代码编译成的字节码指令
ConstantValue字段表final修饰的基础数据类型的类变量(static)的值,虚拟机使用这个属性为变量赋值,使用常量池索引
Deprecated类,方法表,字段表被声明为deprecated的方法和字段,在代码中使用@deprecated注解,没有内容,长度为0
Exceptions方法表方法抛出的异常列表,列举出方法可能抛出的受查异常,使用多个常量池索引,索引项为CONSTANT_Class_info
EnclosingMethod类文件仅当一个类为局部类或者匿名类时才能拥有这个属性,这个属性用于标示这个类所在的外围方法
InnerClasses类文件内部类列表,如果一个类定义了内部类,那么本类和其内部类都会有这个属性。保存了多个inner_class_info表
LineNumber TableCode属性Java源码的行号与字节码指令的对应关系,使用多个line_number_table,由一个u2的start_pc指向字节码行号,以及一个u2的line_number指向Java源码行号
LocalVariableTableCode属性描述栈帧中局部变量表与Java源码中定义的变量之间的关系,使用多个local_variable_info,在jdk5引入泛型后,使用LocalVariableTypeTable表示字段的特征签名
StackMapTableCode属性JDK6中新增的属性,供新的类型检查验证器Type Checker检查和处理目标方法的局部变量和操作数栈所需要的类型是否匹配,包含多个栈映射帧
Signature类, 方法表,字段表JDK 5中新增的属性,用于支持范型情况下的方法签名。在Java语言中,任何类、接口、初始化方法或成员的泛型签名如果包含了类型变量(TypeVariables)或参数化类型(Parameterized Types),则Signature属性会为它记录泛型签名信息。由于Java的范型采用擦除法实现,为了避免类型信息被擦除后导致签名混乱,需要这个属性记录范型中的相关信息,包含一个常量池CONSTANT_Utf8_info项的索引,表示一个泛型签名信息
SourceFile类文件记录源文件名称,使用一个常量池索引
SourceDebugExtension类文件JDK 5中新增的属性,用于存储额外的调试信息。譬如在进行JSP 文件调试时,无法通过Java堆栈来定位到JSP文件的行号,JSR45提案为这些非Java语言编写,却需要编译成字节码并运行在Java虚拟机中的程序提供了一个进行调试的标准机制,使用该属性就可以用于存储这个标准所新加入的调试信息
Synthetic类,放发表,字段表标识方法或字段为编译器自动生成的,没有内容,长度为0
LocalVariableTypeTableJDK 5中新增的属性,它使用特征签名代替描述符,是为了引入泛型语法之后能描述泛型参数化类型而添加
RuntimeVisibleAnnotations类,方法,字段表JDK5中新增的属性,为动态注解提供支持。该属性用于指明哪些注解是运行时(实际上运行时就是进行反射调用)可见的,包含多个annotation表项,每一个都代表一个运行时可见的注解
RuntimelnvisibleAnnotations类,方法,字段表JDK5中新增的属性,与RuntimeVisibleAnnota-tions属性作用刚好相反,用于指明哪些注解是运行时不可见的
RuntimeVisibleParameterAn-notations方法表JDK5中新增的属性,作用与RuntimeVisibleAnnotations属性类似,只不过作用对象为方法参数
RuntimelnvisibleParamcterAnnotations方法表JDK5中新增的属性,作用与 RuntimcInvisibleAnnotations属性类似,只不过作用对象为方法参数
AnnotationDefault方法表JDK5中新增的属性,用于记录注解类元素的默认值
BootstrapMethods类文件JDK7中新增的属性,用于保存invoke dynamic指令引用的引导方法限定符。如果某个类文件结构的常量池中曾经出现过CONSTANT_InvokeDynamic_info类型的常量,那么这个类文件的属性表中必须存在一个明确的BootstrapMethods属性,另外,即使CONSTANT_InvokeDynamic_info类型的常量在常量池中出现过多次,类文件的属性表中最多也只能有一个BootstrapMethods属性,包含多个bootstrap_method项,代表了一个引导方法。还包含了这个引导方法静态参数的序列(可能为空)
RuntimeVisibleTypeAnnotations类,方法,字段表JDK 8中新增的属性,为实现JSR308中新增的类型注解提供的支持,用于指明哪些类注解是运行时(实际上运行时就是进行反射调用)可见的
RuntimelnvisibleTypeAnnotations类,方法,字段表JDK 8中新增的属性,为实现JSR308中新增的类型注解提供的支持,与RuntimeVisibleTypeAnnotations属性作用刚好相反,用于指明哪些注解是运行时不可见的
MethodParameters方法表JDK 8中新增的属性,用于支持(编译时加上-parameters参数)将方法名称编译进Class文件中,并可运行时获取。此前要获取方法名称(典型的如IDE的代码提示)只能通过JavaDoc中得到。包含多个parameter项
ModuleJDK 9中新增的属性,用于记录一个 Module的名称以及相关信息(requires ,exports.opens, uses ,provides), 模块化相关属性
ModulePackagesJDK9中新增的属性,用于记录一个模块中所有被exports或者open的包,包含多个常量池CONSTANT_Package_info项索引
ModuleMainClassJDK 9中新增的属性、用于指定一个模块的主类,包含一个常量池CONSTANT_Class_info项索引
NestHostJDK 11中新增的属性,用于支持嵌套类(Java中的内部类)的反射和访问控制的API,一个内部类通过该属性得知自己的宿主类
NestMembersJDK 11中新增的属性,用于支持嵌套类(Java中的内部类)的反射和访问控制的API,一个宿主类通过该属性得知自己有哪些内部类

属性表大体结构

​ 对于一个合法的属性表,大体结构如下:

类型名称数量意义
u2attribute_name_index1指向一个常量表中的CONSTANT_Utf8_info类型,标识属性的名称
u4attribute_length1标识属性表的长度,以字节为单位,不包括attribute_name_index和attribute_length所占用的6字节
u1infoattrubute_length属性的值,对于每一个属性表来说,这一项的结构和意义是不同的

各个属性表

Code属性表结构

类型名称数量意义
u2attribute_name_index1指向一个常量表中的CONSTANT_Utf8_info类型,标识属性的名称
u4attribute_length1标识属性项的长度
u2max_stacks1操作数栈深度的最大值,虚拟机需要根据这个值分配栈帧中操作栈的深度
u4max_locals1以槽(Slot)为单位代表局部变量(方法参数,显式异常处理的参数,方法体中的局部变量)所需的存储空间,注意这个空间是重用的,即一个变量因为超出作用域,其内存被释放后可用于存放下一个局部变量
u4code_length1字节码指令的长度,以字节为单位
u1codecode_length存放由Java代码翻译出的中间码,字节码,由于是8位的,总共可表达256条指令,目前以定义约200条
u2exception_table_count1异常表的数量
exceptionexception_tableexception_table_count异常表项
u2attributes_count1属性表的数量
attribute_infoattributesattributes_count

异常项目结构(code中的异常表项)

类型名称数量意义
u2start_pc1
u2end_pc1
u2handler_pc1
u2catch_type1常量池索引,索引处的项为CONSTANT_Class_info

如果在start_pc和end_pc之间出现了catch_type类型的异常,那么转到handler_pc处执行,入宫catch_type的索引值为0,代表捕获任何异常

local_variable_info项目结构

类型名称数量意义
u2start_pc1生命周期开始的字节码偏移量
u2length1作用范围的字节码偏移
u2name_index1常量池索引,索引项为CONSTANT_Class_info,表示局部变量的名称
u2descriptor_index1常量池索引,索引项为CONSTANT_Class_info,表示局部变量的描述符
u2index1这个局部变量在栈帧中局部变量槽的起始位置

inner_class_info表结构

类型名称数量内容
u2inner_class_info_index1常量池CONSTANT_Class_info项索引,内部类的符号引用
u2outer_class_info_index1常量池CONSTANT_Class_info项索引,外部类的符号引用
u2inner_name_index1常量池CONSTANT_Utf8_info项索引,内部类类名
u2inner_class_access_flags1内部类访问标志位

栈映射帧

每个栈映射帧都显式或者隐式的代表了一个字节码偏移量,用于表示执行到该字节码时局部变量表和操作数栈的验证类型。类型检查验证器会通过检查目标方法的局部变量和操作数栈所需要的类型来确定一段字节码指令是否符合逻辑约束.

bootstrap_method结构

类型名称数量内容
u2bootstrap_name_index1对常量池CONSTANT_MethodHandle_info项的索引
u2num_bootstrap_arguments1bootstrap_argument的数量
u2bootstrap_argumentsnum_bootstrap_arguments对常量池中CONSTANT_String_info、CONSTANT_Class_info、CONSTANT_Integer_info、CONSTANT_Long_info、CONSTANT_Float_info、CONSTANT_Double_info、CONSTANT_MethodHandle_info或CONSTANT_MethodType_info其中一项的索引

parameter结构

类型名称数量内容
u2name_index1常量池中CONSTANT_Utf8_info项的索引
u2access_flags1是否final修饰,编译器自动生成,隐式定义(比如this)

模块化相关属性

Module属性结构
类型名称数量内容
u2attribute_name_index1属性名
u4attribute_length1属性字节长度
u2module_name_index1常量池CONSTANT_Utf8_info项索引,模块名
u2module_flags1模块是否开放,是否由编译器自动生成而非出现在源文件中,是否在源文件中隐式定义
u2module_version_index常量池CONSTANT_Utf8_info项索引,模块版本号
u2requires_count
requirerequires
u2exports_count导出包的数量
exportexports每一个export项代表一个被模块所导出的包,
u2opens_count
openopens
u2uses_count
useuses_index
u2provides_count
provideprovides
exports项结构
类型名称数量内容
u2exports_index1常量池CONSTANT_Package_info项索引,代表该模块导出的包
u2exports_flags1被导出包的状态指示器,是否由编译器自动生成而非源自源文件,是否该导出包是在源文件中隐式定义的
u2exports_to_count1导出包的限定计时器,如果为0,则该导出包无限定,即完全开放
exportexports_to_indexexports_to_count常量池中CONSTANT_Module_info项索引,代表能够访问导出包的模块

annotation结构

类型名称数量内容
u2type_index1以字段描述符形式表示一个注解,常量池CONSTANT_Utf8_info项索引
u2num_element_value_pairs1
element_value_pairelement_value_pairnum_element_value_pairs作为一个键值对,代表注解的参数和值
这篇关于Java字节码文件(.class)结构略解3-属性表的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!