彻底让你搞懂什么是Java字节码

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第18天,点击查看活动详情

什么是字节码?

因为JVM针对各种操作系统和平台都进行了定制,无论在什么平台,都可以通过javac命令将一个.java文件编译成固定格式的字节码(.class文件)供JVM使用。之所以被称为字节码,是因为 .class文件是由十六进制值组成的,JVM以两个十六进制值为一组,就是以字节为单位进行读取
格式如下:

bytecode.png

字节码的组成结构是什么?

JVM对字节码的规范是有要求的,要求每一个字节码文件都要有十部分固定的顺序组成,如下图: bytecode2.png

1. 魔数

所有的.class文件的前4个字节都是魔数,魔数以一个固定值:0xCAFEBABE,放在文件的开头,JVM就可以根据这个文件的开头来判断这个文件是否可能是一个.class文件,如果是以这个开头,才会往后执行下面的操作,这个魔数的固定值是Java之父James Gosling指定的,意为CafeBabe(咖啡宝贝)

2. 版本号

版本号是魔术之后的4个字节,前两个字节表示次版本号(Minor Version),后两个字节表示主版本号(Major Version),上面的0000 0032,次版本号0000转为十进制是0,主版本号0032 转为十进制50,对应下图的版本映射关系,可以看到对应的java版本号是1.6

bytecodeversion.png

3. 常量池

紧接着主版本号之后的字节为常量池入口,常量池中有两类常量:字面量和符号引用,字面量是代码中申明为Final的常量值,符号引用是如类和接口的全局限定名、字段的名称和描述符、方法的名称和描述符。常量池整体分为两个部分:常量池计数器以及常量池数据区 changlangchi.png

4. 访问标志

常量池结束后的两个字节,描述的是类还是接口,以及是否被Public、Abstract、Final等修饰符修饰,JVM规范规定了9种访问标示(Access_Flag)JVM是通过按位或操作来描述所有的访问标示的,比如类的修饰符是Public Final,则对应的访问修饰符的值为ACC_PUBLIC | ACC_FINAL,即0x0001 | 0x0010=0x0011 access_flag.png

5. 当前类索引

访问标志后的两个字节,描述的是当前类的全限定名,这两个字节保存的值是常量池中的索引值,根据索引值就能在常量池中找到这个类的全限定名

6. 父类索引

当前类名后的两个字节,描述的父类的全限定名,也是保存的常量池中的索引值

7. 接口索引

父类名称后的两个字节,是接口计数器,描述了该类或者父类实现的接口数量,紧接着的n个字节是所有接口名称的字符串常量的索引值

8. 字段表

用于描述类和接口中声明的变量,包含类级别的变量和实例变量,但是不包含方法内部声明的局部变量,字段表也分为两个部分,第一部分是两个字节,描述字段个数,第二部分是每个字段的详细信息fields_info

field.png

9. 方法表

字段表结束后为方法表,方法表也分为两个部分,第一个部分是两个字节表述方法的个数,第二部分是每个方法的详细信息 方法的访问信息比较复杂,包括方法的访问标志、方法名、方法的描述符和方法的属性:

method.png

10. 附加属性

字节码的最后一部分,该项存放了在该文件中类或接口所定义属性的基本信息。

猜你喜欢

转载自juejin.im/post/7107970731157225508