Java 号称“一次编译到处运行”,你知道它的执行过程吗?今天我来给大家分享一下
整篇干货我们通过具体的 demo 来深入理解:
1、首先我们来写一个java源文件
2、编译。用 javac 或者ide工具将该java源文件编译成java 字节码 文件。
下面,再上一张java字节码的总览图,剩下的我们按照顺序一步一步解读。
1、 魔数 ,就是区分文件类型的一种标志。对应我们Demo的就是0XCAFE BABE。
2、版本号,版本号分主版本号和次版本号,都是各占2个字节。在此Demo种为0X0000 0033。前面的是次,后面的是主。通过进制转换得到的是次版本号为0,主版本号为51。
3、常量池,常量池是 class文件 中的资源仓库,主要是 字面量 和符号引用。
下面来一张常量池的项目类型表,JDK1.7之后可能还有新加的,还是按照Demo的字节码进行逐一翻译。
4、Access_Flag 访问标志,访问标志信息包括该Class文件是类还是接口,是否被定义成public,是否是abstract,如果是类,是否被声明成final。通过上面的源代码,我们知道该文件是类并且是public。
注意:0x 00 21:是0x0020和0x0001的并集。其中0x0020这个标志值涉及到了字节码指令,这里暂不多说
5、类 索引 ,类索引用于确定类的全限定名
0x00 03 表示引用第3个常量,同时第3个常量引用第19个常量,查找得”com/demo/Demo”。#3.#19
6、父类索引
0x00 04 同理:#4.#20(java/lang/Object)
7、接口索引
通过java_byte.jpeg图我们知道,这个接口有2+n个字节,前两个字节表示的是接口数量,后面跟着就是接口的表。我们这个类没有任何接口,所以应该是0000。果不其然,查找字节码文件得到的就是0000。
8、字段表集合,字段表用于描述类和接口中声明的变量。这里的字段包含了类级别变量以及实例变量,但是不包括方法内部声明的 局部变量 。
下面上一张字段表结构图
果不其然:
0x00 02 :访问标志为private(自行搜索字段访问标志)
0x00 05 : 字段名称索引为#5,对应的是”a”
0x 00 06 :描述符索引为#6,对应的是”I”
0x 00 00 :属性表数量为0,因此没有属性表。
tips:一些不太重要的表(字段,方法访问标志表)可以自行搜索,这里就不贴出来了,防止篇幅过大。
9、方法,方法解析,按照下图解析(Java学习群632119504)
10、方法解析完成,解析Attributes一下就可以了
其实,我们写了这么多确实很麻烦,不过这种过程自己体验一遍的所获所得还是不同的。这样以后我们也能看懂字节码文件了。了解class文件的结构对后面进一步了解虚拟机执行引擎非常重要,所以这是基础并重要的一步。(Java、Java、Java、Java、Java、Java、Java、Java、Java、Java、Java、Java、Java、Java、Java、Java、Java、Java、Java、Java、Java、Java、Java、Java、Java、Java、Java、Java、Java、Java、Java、Java、Java、)
最后来看一下使用java自带的反编译器来解析字节码文件是什么样子的吧