当前位置: 亚洲城ca88 > ca88 > 正文

Java字节码的结构,深入理解字节码文件

时间:2019-05-24 06:22来源:ca88
hello world 参考《Java虚拟机标准JavaSE七版》的叙述来看,每叁个字节码文件其实都对应着全局唯一的二个类依然接口的定义音讯。字节码文件接纳的是一类别似于C语言结构体的伪结构来
hello world

参考《Java虚拟机标准JavaSE七版》的叙述来看,每叁个字节码文件其实都对应着全局唯一的二个类依然接口的定义音讯。字节码文件接纳的是一类别似于C语言结构体的伪结构来叙述字节码文件格式。为了防止与类的字段、实例等概念发生模糊,本书将用于描述类组织格式的故事情节定义为项(item)

class文件结构

Class文件存款和储蓄的故事情节称为字节码,蕴涵了JVM指令集和符号表以及若干别的扶助消息。

class文件是壹组以8人字节为根基单位的二进制流,各类数据项目严厉遵守顺序紧密的排列在Class文件中,中间未有增加其它分隔符,整个Class文件中贮存的从头到尾的经过差非常的少任何是程序运维的要求的多寡,未有空隙存在。

当境遇七位字节以上的空间的数额项时,则会遵照高位在前的主意划分成几何个5人字节进行仓库储存。

Class文件中有三种数据类型,分别是无符号数和表。

 

每一项都席卷项目、名称以及该项的数量。类型能够是申明,也足以是“基本项目”。蕴含在字节码文件中,各样依照严峻的次第实行一连存放,其里面并不含有其余的相间符区分段落。在此大家供给专注,这几个结构体中唯有二种数据结构,分别是无符号数和表,个中无符号数属于字节码文件中的“基本项目”,字节码文件中的无符号数有u1/u2/u4/u8,分别表示1个字节无符号类型、三个字节无符号类型、5个字节无符号类型、7个字节无符号类型。

无符号数

无符号数属于主旨的数据类型,以u1、u二、u四、u八来代表二个字节、多少个字节...的无符号数;无标记数用来说述数字、索引引用、数量值或UTF-八编码构成的字符串值。

class字节码文件

表是由七个无符号数可能此外表作为数据项构成的复合数据类型,全部表的后缀都以利用“_info”进行最后,并且字节码文件精神上约等于一张表。每二个字节码文件对应着三个ClassFile的构造,如下所示:

表是由四个无符号数或其它表作为数据项组成的复合数据类型,一般以"_info"结尾,用来说述class文件的数据结构。

特色:节省存款和储蓄空间,升高管理品质

ClassFile { u4 magic; u2 minor_version; u2 major_version; u2 constant_pool_count; cp_info constant_pool[constant_pool_count-1]; u2 access_flags; u2 this_class; u2 super_class; u2 interfaces_count; u2 interfaces[interfaces_count]; u2 fields_count; field_info fields[fields_count]; u2 methods_count; method_info methods[methods_count]; u2 attributes_count; attribute_info attributes[attributes_count]; }
  • 魔数
  • Class文件版本
  • 常量池
  • 做客标识
  • 类索引,父类索引,接口索引群集
  • 字段表集合
  • 方法表集结
  • 属性表群集

u2代表无符号数二个字节u任性味无符号数多个字节

 

Class{

Class文件设计意见和意义

每多少个class字节码文件都唯1对应一个类或接口,class文件中著录中类或接口的基本音信,但反之不成立,不是每个类或接口都有八个唯壹对应的字节码文件,首先类或接口的字节码能够不以文件的艺术存款和储蓄,能够平昔从内部存款和储蓄器中生成字节码,而不产生.class文件,动态代理的原理就是一向内部存款和储蓄器中生成字节码流,依据加载字节码流进行类加载操作,类实例化,生成代理对象。

u4              magic

1. 魔数magic

魔数的不二法门功用是规定那几个文件是或不是为三个能被虚拟机所收受的Class文件。魔数值固定为0xCAFEBABE,不会转移。

字节码文件记录的新闻:魔术,class文件程序版本,常量池数量及常量池表,类或接口的拜访标识,类索引,超类索引,接口数量及接口表,字段数量及字段表,方法数量及方法表,属性属性及属性表,jvm中应用类c结构身体表面示每1种性格,结构体中项目种类有三种,无符号数及表,以 _info结尾代表表,以 u一,u二,u四,u九分别代表一字节,二字节,4字节,八字节无符号数

u2              minor_version

证明magic作用

创设1个class文件 magic.class ,内容是magic test,直接运转java magic操作:

84407@FantJ MINGW64 ~/Desktop$ java magictest▒▒▒▒: ▒▒▒▒▒▒▒▒ magictest ʱ▒▒▒▒ LinkageError java.lang.ClassFormatError: Incompatible magic value 1886741100 in class file magictest

报错意思是:magic争持,然后给了个magic value的十进制数,那么能够识别的magic10进制应该是不怎么啊。

图片 1应该是3405691582

那么,然后本身用javac编写翻译的正常java文件生成class文件,用binary viewer 查看:

图片 2

ClassFile{
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count];
u2 acc_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}

u2             major_version

minor_version、major_version

魔数以往后边3位:表示字节码版本,分别表示Class文件的副、主版本。当今用的最广的多少个本子:jdk一.捌:5贰jdk一.柒:5一jdk一.陆:50

图片 3图片 4

对应版本号是5二,是jdk1.八

图片 5

本子向下包容

魔术:三个字节,用于定义此字节码文件是或不是切合虚拟机规范,保证字节码文件不会威迫虚拟机的广安,若为cafebabe则代表字节码符合虚拟机标准

u2              constant_pool_count

2. constant_pool_count

常量池计数器,值极其constant_pool表中的成员数加壹,占用四个字节

程序版本号:三个字节,前两字节表示次版本号,后两字节表示主版本号,用于定义编写翻译的字节码文件格式版本,低版本虚拟机拒绝运营高版本字节码文件,但高版本虚拟机会向下包容低版本字节码文件

cp_info          constant_pool[constant_pool_count-1]

3. constant_pool[]常量池

Java虚拟机指令实践时重视常量池(constant_pool)表中的标志新闻。

负有的常量池项都有所如下通用格式:

cp_info { u1 tag; u1 info[]; }

info[]项的剧情tag由的项目所调控。tag有效的项目和呼应的取值在下表列出

常量类型
CONSTANT_Class 7
CONSTANT_Fieldref 9
CONSTANT_Methodref 10
CONSTANT_InterfaceMethodref 11
CONSTANT_String 8
CONSTANT_Integer 3
CONSTANT_Float 4
CONSTANT_Long 5
CONSTANT_Double 6
CONSTANT_NameAndType 12
CONSTANT_Utf8 1
CONSTANT_MethodHandle 15
CONSTANT_MethodType 16
CONSTANT_InvokeDynamic 18

常量池数量及常量池表:那有个别至关心珍视要总结类或接口的字面量和符号引用,用于每一个类或接口具有的字面量和标识引用属性不明显一样,全数必要五个字节的长度来表示常量池数目,常量池数目计数从一起首,比方类或接口中一同有四个字面量符号引用,则常量池数目为二,注意,不是从0开始计数,0只怕另有用处,能够用来表示类或接口中未出现的引用,用来代表一流父类java.long.Object全限定名的目录,常量池表是3个数组,一共有18类别型,每一种等级次序有一个tag属性与之对应,constant_utf8_info用于表示文本字符串,类和接口全限定名,字段名称及描述符,方法名称及描述符等常量音信,constant_integer_info用于存款和储蓄int类型的常量新闻,只存款和储蓄int类型的值,不存款和储蓄别的符合引用消息,举例 final int a=一 符号引用音信为a,值为1,constant_float_info用于存款和储蓄float类型常量音信,也是只存款和储蓄float值,不存款和储蓄引用新闻,constant_long_info用于存款和储蓄long类型的常量新闻,constant_double_info用于存款和储蓄double类型的常量消息,constant_class_info用于存款和储蓄指向常量池列表constant_unf8_info类和接口全限定名的可行引用,constant_string_info用于存款和储蓄钦命常量池列表constant_utf8_info某常量项的得力索引,指向文本字符串,constant_fieldref_info用于存款和储蓄指向常量池列表constant_class_info常量项和constant_nameandtype_info常量项的卓有成效索引,constant_methodref_info用于存款和储蓄指向常量池列表constant_class_info常量项和constant_nameandtype_info常量项的得力索引,constant_interfacemethodref_info用于存款和储蓄指向常量池列表constant_class_info常量项和constant_nameandtype_info常量项的灵光索引,constant_nameandtype_info用于存款和储蓄指向常量池列表constant_utf8_info常量项的有用索引,可以通过具备找到对应类及描述符,constant_methodtype_info用于存储指向常量池constant_utf8_info常量项,表示方法类型,找到相应的艺术描述符,constant_methodhandle_info用于表示方法句柄,属性reference_kind表示方法句柄的连串,一-四意味着为字段创造的点子句柄,5-八意味为类格局(构造、实例、静态)成立的句柄,九表示为接口方法创建的句柄,reference_index属性指向依据reference_kind对应的常量池列表,constant_invokedynamic_info用于存款和储蓄当前字节码文件中指点形式bootstrap_method数组的有用索引和针对常量池constant_nameandtype_info常量项的得力索引

u2              access_flags

3.1 CONSTANT_Class_info结构

表示类或接口

CONSTANT_Class_info { u1 tag; u2 name_index;}

name_index务必是对常量池的3个卓有功用索引

constant_utf8_info{
u1 tag;
u2 length;
u1 bytes[length];
}
constant_integer_info{
u1 tag;
u4 bytes;
}
constant_float_info{
u1 tag;
u4 float;
}
constant_long_info{
u1 falg;
u8 long;
}
constant_double_info{
u1 tag;
u4 double;
}
constant_class_info{
u1 tag;
u2 name_index;
}
constant_string_info{
u1 tag;
u2 string_index;
}
constant_fieldref_info{
u1 tag;
u2 class_index;
u2 name_and_type_index;
}
constant_mathodref_info{
u1 tag;
u2 class_index;
u2 name_and_type_index;
}
constant_interfacemathodref_info{
u1 tag;
u2 class_index;
u2 name_and_type_index;
}
constant_nameandtype_info{
u1 tag;
u2 class_index;
u2 descriptor_index;
}
constant_methodhandle_info{
u1 tag;
u2 reference_kind;
u2 reference_index;
}
constant_methodtype_info{
u1 tag;
u2 descriptor_index;
}
constant_invokedynamic_info{
u1 tag;
u2 bootstrap_method_attr_index;
u2 name_and_type_index;
}

u2              this_class

3.2 CONSTANT_Fieldref_info, CONSTANT_Methodref_info和CONSTANT_InterfaceMethodref_info结构

字段:

CONSTANT_Fieldref_info { u1 tag; u2 class_index; u2 name_and_type_index; }

方法:

CONSTANT_Methodref_info { u1 tag; u2 class_index; u2 name_and_type_index; }

接口方法:

CONSTANT_InterfaceMethodref_info { u1 tag; u2 class_index; u2 name_and_type_index; }

class_index务必是对常量池的卓有成效索引,常量池在该索引处的项必须是CONSTANT_Class_info结构,表示叁个类或接口,当前字段或艺术是以此类或接口的成员。

CONSTANT_Methodref_info结构的class_index项的品类必须是类。CONSTANT_InterfaceMethodref_info结构的class_index项的门类必须是接口。CONSTANT_Fieldref_info结构的class_index项的品种既能够是类也能够是接口。

name_and_type_index必须是对常量池的有用索引,表示近日字段或措施的名字和描述符。在三个CONSTANT_Fieldref_info协会中,给定的叙述符必须是字段描述符。而CONSTANT_Methodref_infoCONSTANT_InterfaceMethodref_info中加以的讲述符必须是方法描述符。

做客标识:四个字节,用于定义字节码文件所表示的类或接口的拜会权限,如剖断是类依然接口,类是或不是被abstract修饰,类是或不是被final修饰,  acc_interface表示是接口,acc_annotation表示是表明类型,acc_enum代表是枚举类型,acc_public 代表类或接口是public访问权限,acc_final表示类分歧意被接续,acc_abstract表示类为抽象类,acc_super表示类调用实例方法时需举行特殊操作

u2              super_class

3.3 CONSTANT_String_info结构

用来表示String的组织

CONSTANT_String_info { u1 tag; u2 string_index;}

string_index务必是对常量池的有用索引,常量池在该索引处的项必须是CONSTANT_Utf8_info结构,表示1组Unicode码点连串,那组Unicode码点类别最后会被伊始化为一个String对象。

类索引及父类索引:两个字节,用于存款和储蓄指向常量池constant_class_info对应的有用索引,而constant_class_info存储常量池列表的constant_utf8_info常量项索引,依照此索引可找到类和父类的全限定名

u2              interfaces_count

3.4CONSTANT_Integer_info和CONSTANT_Float_info结构

表示四字节(int和float)的数值常量:

CONSTANT_Integer_info { u1 tag; u4 bytes; } CONSTANT_Float_info { u1 tag; u4 bytes;}

接口数量及接口表:接口属性用于存款和储蓄当前类或接口的直接超类接口数量,接口表是二个数组,记住,只有常量池表从壹上马计数,其他都是从数组下表0早先计数,接口表数组的每三个数组成分存储此类或接口的直接超类接口的立竿见影索引,依照此索引找到constant_class_info对应的常量项,根据constant_class_info可找到呼应直接超类接口的全限定名

u2              interfaces[interfaces_count]

3.5CONSTANT_Long_info和CONSTANT_Double_info结构

代表8字节(long和double)的数值常量

CONSTANT_Long_info { u1 tag; u4 high_bytes; u4 low_bytes; } CONSTANT_Double_info { u1 tag; u4 high_bytes; u4 low_bytes; }

字段数量及字段表:字段数量用于存款和储蓄类或接口的字段数目,蕴含类字段和实例字段,字段表为一个数组,每1个数组成分都也正是三个田野同志_info结构的目的,田野(field)_info结构包涵字段完整音讯:字段标记符,字段访问修饰符,字段是类字段还是实例字段,字段是不是为常量等,注意:此处字段表示方今类或接口的字段,不包蕴从超类或接口继承的字段,java语法标准差异意同二个类或接口中出现同一字段名的不等字段,可是class文件中却能够允许出现同样字段名的差别字段,唯有字段的叙述符区别就可以,田野_info结构属性:access_flags用于存款和储蓄字段的拜访标记,acc_private,acc_protected,acc_public,acc_final,acc_static,acc_volatile等,注意:acc_final与acc_volatile不可能同期出现在同一字段,name_index指向常量池constant_utf8_info常量项的有效索引,获取当前字段的粗略名称,descriptor_index指向常量池constant_utf8_info常量项的有用索引,获取当前字段的描述符,attribute_count,attributes[attributes_count]这两项表示字段的属性音信,用于描述字段相关消息,attribute数组每八个元素都以二个attribute_info结构的要素

u2              fields_count

3.6 CONSTANT_NameAndType_info结构

表示字段或措施,不过和前边介绍的二个组织不一样,CONSTANT_NameAndType_info结构未有标记出它所属的类或接口

CONSTANT_NameAndType_info { u1 tag; u2 name_index; u2 descriptor_index;}

name_index项的值必须是对常量池的实用索引,常量池在该索引处的项必须是CONSTANT_Utf8_info结构,那几个布局如故表示极其的点子名,要么表示多少个实惠的字段或艺术的非限定名(Unqualified Name)。

descriptor_index项的值必须是对常量池的管事索引,常量池在该索引处的项必须是CONSTANT_Utf8_info结构,这一个结构意味着3个实用的字段描述符或格局描述符。

field_info{
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attribuyes_count];
}

field_info        fields[fields_count]

3.7 CONSTANT_Utf8_info结构

用于表示字符串常量的值

CONSTANT_Utf8_info { u1 tag; u2 length; u1 bytes[length]; }

CONSTANT_Utf8_info结构中的内容是以length属性分明长度的

措施数量及方法表:方法数量用于存款和储蓄当前类或接口的主意数目,包罗实例方法,类方式,抽象方法,方法表是3个数组,每贰个数组成分都以一个method_info结构,method_info结构包括方法的完好新闻:方法描述符,访问修饰符,是还是不是为final方法,是或不是为abstract方法等,注意:此处的诀要数组只是意味着近来类或接口的有所办法,并不包含从超类及父接口承袭来的艺术,java语法标准java类或接口中不容许出现方法签字完全平等的不二等秘书籍同期出现,会编写翻译报错,而字节码层面却允许方法签字完全同样的方法同一时候现身,只须求确定保证措施的回到值类型差别,method_info结构属性与田野先生_info一致,但acc_flags类型不尽一样,注意acc_abstract不能与acc_final,acc_static,acc_private,acc_synchronized,acc_native同临时候采纳,接口方法中只好利用acc_public,acc_abstract,此处笔者有1个疑云,接口中default方法有未有相应的访问标识,注意:<init>方法只可以利用acc_private,acc_protected,acc_public访问标记

u2              methods_count

3.8 CONSTANT_MethodHandle_info结构

意味着方法句柄

CONSTANT_MethodHandle_info { u1 tag; u1 reference_kind; u2 reference_index;}

reference_kind项的值必须在1至玖之内,它决定了艺术句柄的花色。

  1. 如果reference_kind项的值为1(REF_getField)、2(REF_getStatic)、3(REF_putField)或4(REF_putStatic),那么常量池在reference_index索引处的项必须是CONSTANT_Fieldref_info结构,表示由1个字段创设的方法句柄。
  2. 如果reference_kind项的值是5(REF_invokeVirtual)、6(REF_invokeStatic)、7(REF_invokeSpecial)或8(REF_newInvokeSpecial),那么常量池在reference_index索引处的项必须是CONSTANT_Methodref_info布局,表示由类的艺术或构造函数创制的艺术句柄。
  3. 如果reference_kind项的值是9(REF_invokeInterface),那么常量池在reference_index索引处的项必须是CONSTANT_InterfaceMethodref_info结构,表示由接口方法创造的秘诀句柄。
  4. 如果reference_kind项的值是5(REF_invokeVirtual)、6(REF_invokeStatic)、7(REF_invokeSpecial)或9(REF_invokeInterface),那么方法句柄对应的情势不能够为实例开首化()方法或类开首化方法()。
  5. 如果reference_kind项的值是8(REF_newInvokeSpecial),那么方法句柄对应的秘籍必须为实例初步化()方法。
method_info{
u2 access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attribuyes_count];
}

method_info     methods[methods_count]

3.9 CONSTANT_MethodType_info结构

表示方法类型

CONSTANT_MethodType_info { u1 tag; u2 descriptor_index; }

品质数据及属性表:属性数据表示最近字节码文件中attribute_info表数目,属性表是一个数组,每三个数组成分都以attribute_info结构,attribute_info结构表示属性的完整新闻:第3项针对常量池constant_utf8_info某常量项的有效索引,依照此索引可找到属性对应名称,属性能够出现在classFile,字段表,方法表中,用以描述相关音讯,attribute_info结构完整音信:attribute_name_index指向常量池constant_utf8_info常量项的得力索引,获取属性名称,attribute_length用于指明info数高管度,info[attribute_length]用以存款和储蓄属性的多少消息,必须贯彻的多寡音信:Code,ConstantValue,Exceptions,  code属性用于描述method_info的现实性相关新闻,attribute_name_index指向常量池constant_utf8_info常量项的实用索引,获取属性名称,即code,attribute_length表示attribute表示attribute_info长度,不包括attribute_name_index和attribute_length的初始6字节,max_stack描述当前格局最大栈深度,max_locals描述当前艺术的有的变量表,code_length表示code数经理度,code[]意味着这段时间艺术编写翻译后的字节码,  ContantVaue位于田野同志_info结构中,用于通告虚拟机对类变量进行开头化,即字段须要被acc_static修饰,当前类常量无需ContantValue文告虚拟机实施初始化,早就实践好了,实例字段此时没有须求开首化

u2              attributes_count

3.10 CONSTANT_InvokeDynamic_info结构

意味着invokedynamic指令所运用到的教导格局(Bootstrap Method)、引导格局应用到动态调用名称(Dynamic Invocation Name)、参数和乞请再次回到类型、以及能够选择性的附加被叫做静态参数(Static Arguments)的常量连串。

CONSTANT_InvokeDynamic_info { u1 tag; u2 bootstrap_method_attr_index; u2 name_and_type_index; }

bootstrap_method_attr_index项的值必须是对脚下Class文件中教导方式表的bootstrap_methods[]数组的有用索引。

name_and_type_index项的值必须是对当下常量池的管事索引,常量池在该索引处的项必须是CONSTANT_NameAndType_info结构,表示方法名和办法描述符。

attribute_info{
u2 attribute_name_index;
u4 attribute_length;
u1 info[attribute_length];
}

code_attribute{
u2 attribute_name_index;
u4 attribute_length;
u2 max_stack;
u2 max_locals;
u4 code_length;
u1 code[code_length];
u2 exception_table_length;
exception_info exception_table[exception_table_length];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
constantvalue_attribute{
u2 attribute_name_index;
u4 attribute_length;
u2 constantvalue_index;
}

attribute_info     attributes[attributes_count]

4. access_flags:访问标识

走访标记,access_flags是一种掩码标记,用于表示有个别类依然接口的拜访权限及基础属性。access_flags的取值范围和相应含义见下表。

标记名 含义
ACC_PUBLIC 0x0001 可以被包的类外访问。
ACC_FINAL 0x0010 不允许有子类。
ACC_SUPER 0x0020 当用到invokespecial指令时,需要特殊处理的父类方法。
ACC_INTERFACE 0x0200 标识定义的是接口而不是类。
ACC_ABSTRACT 0x0400 不能被实例化。
ACC_SYNTHETIC 0x1000 标识并非Java源码生成的代码。
ACC_ANNOTATION 0x2000 标识注解类型
ACC_ENUM 0x4000 标识枚举类型

粗略名称与叙述符:

}

5. this_class:类索引

this_class的值必须是对constant_pool表中项指标1个有效索引值。

是二个对constant_pool表中项目标3个有效索引值,表示针对常量池的第多少个任务。

简单易行名称是指字段或方法的大致的一种描述,举个例子person class:private String name字段轻易名名字为name,Object class:public String toString()方法简便名字为toString,注意:字段或艺术大约名称不允许出现  .  :  / [ 等ASSIC或Unicode字符表示情势

至于ClassFile结构的叙说音信,如下所示:

6. super_class:父类索引

表示这几个Class文件所定义的类的直接父类,就算Class文件的super_class的值为0,这这么些Class文件只大概是概念的是java.lang.Object类,唯有它是唯一未有父类的类

是1个对constant_pool表中项指标贰个有效索引值,表示针对常量池的第多少个岗位。

讲述符一般指字段或方法的品类,字段描述符表示字段类型描述,方法描述符表示参数描述与重临值描述,如:person class:private String name字段描述符为Ljava.lang.String,com.test.Person class:setName(String name)方法描述符为(Ljava.lang.String)V,注意:其中V表示重临值为void类型,固然参数为void则意味为()Ljava.lang.Object,表示无参的重临值为java.lang.Object引用类型的措施描述符

一)  magic 魔术字符

7. interfaces_count:接口计数器

意味着有其一类有多少个接口。

字段描述符解释:B byte 字节项目,Z boolean 布尔等级次序,C char 字符类型,S short 短整型,I 整型,L long 长整型,F float 单进程浮点类型,D double 双精度浮点类型,L reference 对象引用类型,[ reference 数组引用类型

1个有效地字节码文件的前七个字节为0xCAFEBABE,(咖啡宝物),也叫做魔术字符。JVM用魔术字符来校验八个对象class文件是或不是是合法的。

8. interfaces[]:接口表

成员所表示的接口顺序和相应的源代码中加以的接口顺序同样,即interfaces[0]对应的是源代码中最左侧的接口。

是贰个对constant_pool表中项指标一个有效索引值,表示针对常量池的第多少个地点。

表示最近类或接口的直接父接口数量

2)  minor_version(此版本号)和major_version(主版本号)

9. fields_count:字段计数器

意味着最近Class文件田野同志s[]数组的分子个数

紧跟在magic之后的5个字节就是编写翻译的次版本号和主版本号,他们手拉手组成了字节码文件的版本号。假使字节码文件的版本号超过了JVM所能够管理的可行限制,那么Java虚拟机将不会管理那几个字节码文件。可是高版本的JVM却能向下包容运转由低版本JDK编写翻译的字节码文件。

10. fields[]:字段表

每一个成员都不可能不是八个田野同志s_info结构的数码项,描述当前类或接口注解的有着字段,但不包罗从父类或父接口承继的有的。

用来表示最近类或接口中某些字段的完全描述

field_info { u2 access_flags; u2 name_index; //对常量池的一个有效索引 u2 descriptor_index; //对常量池的一个有效索引 u2 attributes_count; //当前字段的附加属性的数量 attribute_info attributes[attributes_count];}

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_VOLATILE 0x0040 volatile,表示字段是易变的。
ACC_TRANSIENT 0x0080 transient,表示字段不会被序列化。
ACC_SYNTHETIC 0x1000 表示字段由编译器自动产生。
ACC_ENUM 0x4000 enum,表示字段为枚举类型。

attributes表的种种成员的值必须是attribute结构,一个字段能够有私下个关系属性。

3)  constant_pool_count(常量池计数器)和constant_pool(常量池)

11. methods_count:方法计数器

methods_count的值表示近日Class文件methods[]数组的成员个数,Methods[]数组中每1项都是三个method_info结构的数量项。

在字节码文件中,紧跟在次版本号和主版本号之后的便是常量池计数器和常量池。常量池是字节码文件中1贰分关键的多少项,同期也是字节码文件中与其余项事关最大和占用字节码空间最大的数据项。常量池首要存放字面量(Literal)和标识引用(Symbolic References)两大类数据常量,其访问方式是通过索引来举办访问的,但由于常量池列表中的数量并不固定,因此在常量池在此以前就必要通过1个二个字节的常量池计数器来总括常量池列表中到底具备多少常量项。在此大家只顾,常量池计数器中的计数值并不是从0伊始开始展览计数的,而从一上马,也正是说,假诺常量池中有多少个常量时,计数值为2。

12. methods[]:方法表

method_info结构能够代表类和接口中定义的具备办法,包涵实例方法、类方式、实例伊始化方法情势和类或接口伊始化方法措施。methods[]数组只描述当前类或接口中宣示的方法,不包含从父类或父接口承袭的法子。

methods[]数组中的每种成员都必须是八个method_info结构的数目项,用于表示如今类或接口中有个别方法的全部描述。

method_info { u2 access_flags; u2 name_index; u2 descriptor_index; u2 attributes_count; attribute_info attributes[attributes_count]; }

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_SYNCHRONIZED 0x0020 synchronized,方法由管程同步
ACC_BRIDGE 0x0040 bridge,方法由编译器产生
ACC_VARARGS 0x0080 表示方法带有变长参数
ACC_NATIVE 0x0100 native,方法引用非java语言的本地方法
ACC_ABSTRACT 0x0400 abstract,方法没有具体实现
ACC_STRICT 0x0800 strictfp,方法使用FP-strict浮点格式
ACC_SYNTHETIC 0x1000 方法在源文件中不出现,由编译器产生

name_indexdescriptor_index 两属性是对常量池的3个行之有效索引attributes_count的项的值表示那么些主意的叠合属性的数额。attributes 表的每多个成员的值必须是attribute结构,一个措施能够有自由个与之有关的性质。

常量池中存放的字面量由文字字符串、final常量值等结合,而符号引用则囊括了类和接口的全限定名(Fully Qualified Name)、字段的称呼和讲述符(Descriptor),以及艺术的称谓和描述符。

13. attributes_count:属性计数器

attributes表中每一项都以四个attribute_info结构的数码项。

attributes_count的值表示近日Class文件attributes表的积极分子个数。

4)  access_flags(访问标识)

14. attributes[]:属性表

attributes表的每个项的值必须是attribute_info结构,在Class文件格式中的ClassFile结构、田野先生_info结构,method_info结构和Code_attribute结构都有利用,全数属性的通用格式如下:

attribute_info { u2 attribute_name_index; u4 attribute_length; u1 info[attribute_length];}

attribute_name_index务必是对现阶段Class文件的常量池的有效15位无符号索引。表示如今质量的名字。

attribute_length项的值给出了跟随其后的字节的尺寸,这一个长度不包涵attribute_name_indexattribute_name_index项的6个字节。

紧跟在常量池事后的一个字节是造访标识,访问标识正是用来表示有些类还是接口的访问权限。譬如:访问标识指明的是字节码文件中的类依旧接口;使用的拜会修饰符是哪1种,是不是是由abstract关键字修饰的抽象类;如若是被abstract修饰的抽象类,不能够再标志为final类型;接口类型一样也不允许被final修饰。访问标记的定义如下所示(仅列举二项,具体请看书):

14.1 ConstantValue属性

ConstantValue属性是定长属性,位于田野_info结构的性质表中。假诺该字段为静态类型(即田野(field)_info结构的access_flags项设置了ACC_STATIC标记),则表明这么些田野同志_info结构表示的常量字段值将被分配为它的ConstantValue属性表示的值,那些进程也是类或接口申明的常量字段(Constant Field)初阶化的一片段。这些进度产生在引用类或接口的类开头化方法施行从前。

ConstantValue_attribute { u2 attribute_name_index; u4 attribute_length; u2 constantvalue_index; }

attribute_name_index项的值,必须是三个对常量池的实惠索引。attribute_length项的值固定为二。constantvalue_index项的值,必须是七个对常量池的有效性索引。

做客标记

14.2 Code属性

Code属性是贰个变长属性,位于method_info结构的属性表。3个Code属性只为唯13个措施、实例类开头化方法或类开首化方法保存Java虚拟机指令及有关支持新闻。全数Java虚拟机达成都不可能否够辨识Code属性。假若措施被声称为native只怕abstract类型,那么相应的method_info结构不可能有拨云见日的Code属性,其它景况下,method_info有必须有分明的Code属性。

Code_attribute { u2 attribute_name_index; u4 attribute_length; u2 max_stack; u2 max_locals; u4 code_length; u1 code[code_length]; u2 exception_table_length; { u2 start_pc; u2 end_pc; u2 handler_pc; u2 catch_type; } exception_table[exception_table_length]; u2 attributes_count; attribute_info attributes[attributes_count];}

attribute_name_index项的值必须是对常量池的卓有功用索引attribute_length项的值表示近些日子质量的尺寸,不蕴涵早先的四个字节。max_stack项的值给出了近来艺术的操作数栈在运维实行的其他时间点的最大深度。max_locals项的值给出了分配在时下格局引用的1对变量表中的局地变量个数,包蕴调用此格局时用来传递参数的一些变量。long和double型的部分变量的最大索引是max_locals-贰,别的项目标局地变量的最大索引是max_locals-1.code_length项给出了脚下艺术的code[]数组的字节数,code_length的值必须大于0,即code[]数组不能够为空。code[]数组给出了实现当前艺术的Java虚拟机字节码。exception_table_length项的值给出了exception_table[]数组的积极分子个数据。exception_table[]数组的各类成员代表code[]数组中的二个那一个管理器(Exception Handler)。exception_table[]数组中,非凡管理器顺序是有意义的。start_pcend_pc两项的值表明了那些管理器在code[]数组中的有效限制。handler_pc项表示二个非常管理器的源点如若catch_type项的值不为0,那么它必须是对常量池的一个有效索引attributes_count项的值给出了Code属性中attributes表的分子个数。属性表的种种成员的值必须是attribute结构。叁个Code属性能够有专断数量的可选属性与之提到。

14.3 StackMapTable属性

StackMapTable属性是一个变长属性,位于Code属性的品质表中。这天性子会在虚拟机类加载的品种阶段被应用。

StackMapTable_attribute { u2 attribute_name_index; u4 attribute_length; u2 number_of_entries; stack_map_frame entries[number_of_entries];}

attribute_name_index项的值必须是对常量池的有效性索引attribute_length项的值表示目前品质的长短,不包罗开头的陆个字节。number_of_entries项的值给出了entries表中的成员数量。Entries表的种种成员是都以3个stack_map_frame协会的项。entries表交给了近日艺术所需的stack_map_frame结构。

...越多的本性就不在那壹一贴了,太多了,需求的时候查官方文档就能够:

描述

字节码指令

java虚拟机指令由三个字节长度的,代表某种特定操作含义的数字,以及随后的代表此操作所需参数的操作数而结成。

操作码的长度为叁个字节,所以最大唯有25陆条

ACC_PUBLIC

常量入栈指令

图片 6

0x0001

一对变量值转载到栈中指令

图片 7

声称为public,可以被包的类举办外访问

将栈顶值保存到部分变量中指令

图片 8

ACC_FINAL

wide指令

图片 9

0x0010

通用栈操作指令

图片 10

扬言为final,不允许有派生类

类型转变指令

图片 11

5)  this_class(类索引)和super_class(超类索引)

平头运算

图片 12

紧跟在拜访标识之后的5个字节正是类索引和超类索引,类索引和超类索引各自会通过索引指向常量池列表中的贰个类型为CONSTANT_Class_info的常量项。CONSTANT_Class_info由tag和name_index两局地构成,tag是贰个具备CONSTANT_Class_info值的常量,而name_index则是指向常量池列表中类型为CONSTANT_Utf8_info常量项的目录,通过那一个目录就可以成功博获得CONSTANT_Utf8_info常量项中的全限定名字符串,如下图所示。简单的话,类索引用于规定当前类的全限定名,而超类索引则用来鲜明当前类的超类的全限定名。

浮点运算

图片 13

图片 14

逻辑运算——移位运算

图片 15

6)  interfaces_count(接口计数器)和interface(接口表)

逻辑运算——按位布尔运算

图片 16

在类索引和超类索引之后的五个字节就是接口计数器和接口表。接口计数器用于表示最近类如故接口的直白超类接口数量。接口表实际上是一个数组集合,包涵了近日类依旧接口在常量池列表中一向超类接口的目录集结,通过这么些目录就能够显著当前类照旧接口的超类接口的全限定名。

调整流指令——条件跳转指令

图片 17

7)  fields_count(字段计数器)和田野先生s(字段表)

调控流指令——相比指令

图片 18

在接口计数器和接口表之后正是字段计数器和字段表。字段计数器用于表示3个字节码文件中的田野同志_info表总量,也正是3个类中类变量和实例变量的数量总和。而字段表实际上则是3个数组集结,字段表中的每几个分子都无法不是一个田野先生_info结构的多寡项。轻巧的话,田野先生_info用于表明1个字段的全体音讯,举例字段的表示符、访问修饰符(public/private/protected)、是类变量如故实例变量(static 修饰符)、是或不是是常量(final修饰符)。字段表中所包括的字段音讯只限于当前类或接口的所属字段,并不带有承继超类后的字段新闻。

调节流指令——无条件跳转指令

图片 19

8)  methods_count(方法计数器)和methods(方法表)

调控流指令——表跳转指令

图片 20

在字段计数器和字段表之后正是方法计数器和方法表。方法计数器用于表示三个字节码文件中的method_info表总量。而艺术表实际上是叁个数组会集,方法表中的每一个成员都不能够不是2个method_info结构的多寡项。轻松的话,method_info用于表示近些日子类仍旧接口中某些方法的全体描述,比方方法标示符、方法的走访修饰符、方法的回到值类型以及艺术的参数新闻等。方法表中所包蕴的办法音信只限于当前类依旧接口中的所属方法,并不带有承接超类后的点子新闻。

调节流指令——非凡和finally

图片 21

9)  attribute_count(属性计数器)和attributes(属性表)

对象操作指令

图片 22

在措施计数器和方法表之后的就是属性计数器和属性表。属性计数器用于表示方今字节码文件中的attribute_info表总的数量。而属性表同在此之前的字段表和方法表同样都以三个数组集合,属性表中的每多个成员都必须是3个attribute_info结构的数据项。每贰个attribute_info表的第二项都以指向常量池列表中的CONSTANT_Utf8_info项的目录,该表给出了质量的名号。

数组操作指令

图片 23

属性能够出现在ClassFile表、字段表和章程表中,用以描述与其有关的新闻,举例描述字节码文件中所定义的类和接口相关的消息、描述与字段相关的消息、描述与办法有关的新闻。

主意调用指令

图片 24

摘自《Java虚拟机精讲》高翔龙

方法重返指令

图片 25

线程同步指令

图片 26

命令参谋:

1个简易的demo解析

public class Test { public static void main(String[] args) { int a = 10; int b = 20; int c = a b; System.out.println; }}

 #2 = Fieldref #24.#25 // java/lang/System.out:Ljava/io/PrintStream; #3 = Methodref #26.#27 // java/io/PrintStream.println:V public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags:  ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=4, args_size=1 0: bipush 10 //把10扩展成int入栈 2: istore_1 //将栈顶int类型值保存到局部变量1中 3: bipush 20 //把20扩展成int入栈 5: istore_2 //将栈顶int类型值保存到局部变量2中 6: iload_1 //从局部变量1中装载int类型值入栈 7: iload_2 //从局部变量2中装载int类型值入栈 8: iadd // 将栈顶两int类型数相加,结果入栈。 9: istore_3 //将栈顶int类型值保存到局部变量3中 10: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;获取静态字段的值。#2表示常量池的索引 13: iload_3 14: invokevirtual #3 // Method java/io/PrintStream.println:V 运行时方法绑定调用方法。 17: return //void函数返回。

编辑:ca88 本文来源:Java字节码的结构,深入理解字节码文件

关键词: 亚洲城ca88