目录
1.Demo源码
2.字节码
3.class文件反编译java文件
4.字节码结构
4.1 魔数
编辑4.2 版本号
4.3 常量池
4.3.1 常量池计数器
4.3.2 常量池表
编辑4.3.3 常量类型和结构
4.3.4 常量解读
5.访问标识
6.类索引、父类索引、接口索引
7.字段表集合
8.方法表集合
9.属性表集合
1.Demo源码
首先,编写一个简单的Java源码:
package com.april.test;
public class Demo {
private int num = 1;
public int add() {
num = num + 2;
return num;
}
}
2.字节码
要运行一段Java源码,必须先将源码转换为class文件,class文件就是编译器编译之后供虚拟机解释执行的二进制字节码文件,可以通过IDE工具或者命令行去将源码编译成class文件。这里我们使用命令行去操作,运行下面命令:
javac Demo.java
就会生成一个Demo.class文件。
我们打开这个Demo.class文件看下。这里用到的是Notepad++,需要安装一个HEX-Editor插件。
字节码格式文件为16进制,在excel中打开,一个单元格就为一个字节
3.class文件反编译java文件
在分析class文件之前,我们先来看下将这个Demo.class反编译回Demo.java的结果,如下图所示:
可以看到,回编译的源码比编写的代码多了一个空的构造函数和this关键字,为什么呢?先放下这个疑问,看完这篇分析,相信你就知道答案了。
4.字节码结构
从上面的字节码文件中我们可以看到,里面就是一堆的16进制字节。那么该如何解读呢?别急,我们先来看一张表:
这是一张Java字节码总的结构表,我们按照上面的顺序逐一进行解读就可以了。
首先,我们来说明一下:class文件只有两种数据类型:无符号数和表。如下表所示:
上面各种具体的表的数据结构后面会详细说明,这里暂且不表。
好了,现在我们开始对那一堆的16进制进行解读。
4.1 魔数
从上面的总的结构图中可以看到,开头的4个字节表示的是魔数
Magic Number(魔数)
每个Class文件开头的4个字节的无符号整数称为魔数(Magic Number)
它的唯一作用是确定这个文件是否为一个能被虚拟机接受的有效合法的Class文件。即:魔数是Class文件的标识符。
魔数值固定为0xCAFEBABE。不会改变。
如果一个Class文件不以0xCAFEBABE开头,虚拟机在进行文件校验的时候就会直接抛出以下错误:
使用魔数而不是扩展名来进行识别主要是基于安全方面的考虑,因为文件扩展名可以随意地改动。
png格式的文件也有相同的魔数
mp3格式也有相同的魔数
4.2 版本号
紧接着魔数的4个字节存储的是Class文件的版本号。同样也是4个字节。第5个和第6个字节所代表的含义就是编译的副版本号minor_version,而第7个和第8个字节就是编译的主版本号major_version。
它们共同构成了class文件的格式版本号。譬如某个Class文件的主版本号为M,副版本号为m,那么这个Class文件的格式版本号就确定为M.m