类文件结构
2020-02-26 15:15:06 0 举报
AI智能生成
深入理解jvm虚拟机啊整理--类文件结构
作者其他创作
大纲/内容
2.class类文件的结构
1.概述
无符号数
无符号数属于基本的数据类型,以u1,u2,u4,u8来表示一个字节两个字节4个字节和8个字节。
无符号数可以用来描述数字,索引引用,数量值或者按照UTF-8编码构成的字符串
无符号数可以用来描述数字,索引引用,数量值或者按照UTF-8编码构成的字符串
表
1.表是由多个无符号数或者其他表作为数据项构成的符合数据结构。
2.所有的表都习惯以_info结尾。
3.表用于描述有层次关系的符合结构的数据,整个class文件本质上就是一张表。
2.所有的表都习惯以_info结尾。
3.表用于描述有层次关系的符合结构的数据,整个class文件本质上就是一张表。
2.魔数与class文件的版本
魔数
定义
每个class文件的头四个字节称为魔数,他的唯一作用是确定这个文件是否是能被阻尼及接受的class文件
CA FE BA BE
java版本
class文件紧接着魔数的是class的版本号,56字节是次版本号(mimor version),78字节是主版本号(mojar version)
3.常量池
紧接着java版本的就是常量池入口
常量池容量计数值(constant_pool_count)
u2类型的
索引从1开始
常量
字面量
文本字符串,声明为final的常量值
符号引用
类和接口的全限定名
字段的名称和描述符
方法的名称和描述符
每一个常量都是一个表,jdk中内置了各种常量,类,接口,方法类型的表,这些表开头都是一个u1类型的类型
阅读常量池思路
1.紧跟java版本后面的是常量池数量(u2),代表常量的个数
紧接着是第一个常量的类型,可以根据常量池的项目类型表对应查找
每一种常量类型都有指定的结构,按照这个结构来查找之后的字节码
变异后的常量池都是:方法名,类名之类的都编译为UTF8类型,,常量编译为各自的常量。其他的都引用这些常量
4.访问标志
access_flag,常量池之后就是访问标识
用于识别一些类或者接口层次的访问信息:这个class是接口还是类,是否为public,是否定义为abstract
16个标志位加起来
5.类索引、父类索引与接口索引集合
类索引
u2类型,指向对应的类常量
类的全限定名
父类索引
u2类型,指向对应的类常量
父类的全限定名
接口索引
一组u2类型的集合,分别指向对应的接口常量
class实现的接口,按照顺序显示
6.字段表集合
定义
用于描述接口或者类中声明的变量
可标识的
字段的作用域、实例变量还是类变量、可变性、并发可见性、可否被序列化、字段数据类型、字段名称
结构
access_flags,nameindex,description,attributes_count,attribute_info
字段修饰符
简单名称
全限定名:把类中的.换成/
就是直接的名字
方法和字段的描述符
用来描述字段的数据类型,方法的参数和返回值
字段
根据 描述符标识字符含义 表来表示
数组
前面加 [
方法
先参数列表后返回值
额外的信息,比如默认值
彩蛋
java语法中字段的名称是不能重复的,但是在字节码里面,如果描述符不一样,名称是可以重复的
7.方法表集合
和字段表结构一样,标识了方法
结构,基本和字段表集合一样
访问标识
名称索引
描述符索引
属性表集合
彩蛋,在字节码里面,仅仅返回值不同的方法也是可以重载的
8.属性表集合
code 属性
java程序方法体中代码经过javac编译器处理后,最终变为字节码指令存储在code属性内
结构
attribute_name_index u2
属性名称,指向一个utf8类型的常量
attribute_length u4
属性值的长度,固定为整个属性表的长度-6
max_stack u2
操作数栈深度的最大值
max_locals u2
局部变量表所需要的存储空间,单位为slot
code_length u4
用来存储java源程序编译后生成的字节码指令
code u1
用来存储字节码指令的一系列字节流
exception_table_length u2
exception_table exception_info
start_pc,end_pc,hadle_pc,catch_type
attribute_count u2
attribute attribute_info
exceptions属性
和code平级的exception,不要混淆。作用是列举出方法可能抛出的受查异常,也就是throws后面列举的异常
lineNumberTable属性
用于描述java源码行号与字节码行号之间的对应关系
编译时关闭无法看到日志行号,无法debug
localVariabledTable
用于描述栈帧中局部变量与java源码中定义的变量之间的关系
编译时不生成这个属性别人调用时看不到方法内的参数
SoureFile属性
用于记录生成这个class文件的源码文件名称
编译时不生成改属性,抛出异常时不会显示出错代码所属的文件名
ConstantValue属性
通知虚拟机自动为静态变量赋值,只有static属性修饰的变量才可以使用这项属性
innerClasses属性
用于记录内部类与宿主之间的关系
Deprecated及Synthetic属性
deprecated,用于描述某个类,字段,方法不推荐别人使用
代表此字段或者方法不是由java源码产生的,而是编译器自动生成的
StackMapTable属性
用于验证虚拟机类加载的字节码的验证器
Signature属性
记录泛型类型
BootstrapMethods属性
用来保存invokedynamic指令引用的引导方法
4.共有设计和私有设计
1.无关行的基石
slogan:write one,run anywhere
字节码
3.字节码指令简介
概述
字节码:由一个字节长度、代表着某种特定操作含义的数字以及跟随其后的零至多个代表此操作所需参数而构成
1.字节码与数据类型
byte,short,int,char,boolean,float,double,long,a
2.加载和存储指令
用于将数据在栈帧中的局部变量表和操作数栈之间来回传输
将一个局部变量加载到操作栈
load
将一个数值从操作站存储到局部变量表
store
将一个常量加载到操作数栈
push,ldc,const
扩充局部变量表的访问索引指令:wide
3.运算指令
用于两个操作数栈上的值进行特定运算,并把结果重新存入操作栈顶
加减乘除
add,sub,mul,div
求余,取反
rem,neg
位移,按位或,按位与,按位异或
sh,or,and,xor
局部变量自增指令
iinc
比较指令
cmp
4.类型转换指令
可以将两种不同的数值类型进行相互转换
i2b,i2c,i2s,l2i,f2i,f2l,d2i,d2l,d2f
5.对象创建于访问指令
创建类实例
new
创建数组
newarray
访问类字段和实例字段
getfiled,getstatic
将数组加载到操作数栈
aload
将一个操作数栈的值存储到数组元素中
astore
取数组长度
arraylength
检查类指令
instancsof,checkcase
6.操作数栈管理指令
pop,dup,swap
和操作普通的栈一样
7.控制转移指令
可以让java虚拟机有条件或无条件地从指定的位置指令而不是控制转移指令的下一条指令继续执行程序
跳转
条件
if
复合条件
tableswitch,lookupswitch
无条件分支
goto,goto_w,jsr,jsr_w,ret
8.方法调用和返回指令
invokevirtual
调用对象的实例方法
invokeinterface
调用接口方法
invokespecial
调用需要特殊处理的方法,比如初始化方法,私有方法,父类方法
invokestatic
用于调用类方法
invokedynamic
用于在运行时动态调用解析出来的方法
9.异常处理指令
athrow
10.同步指令
5.Class文件结构的发展
0 条评论
下一页