代码编译的结果从本地机器码转变为字节码,是存储格式发展的一小步,却是编程语言的一大步 ——引言
Class 字节码结构组织
数据类型:
Class 类文件只有两种数据类型:无符号数 和 表。
- 无符号数属于基本的数据类型, 以u1、 u2、 u4、 u8 来分别代表1个字节、2个字节、4个字节、8个字节。
- 表是由多个无符号数或者其他表作为数据项构成的复合数据类型。
可以这样理解:整个Class 文件本质上就是一张表,它由如下表0-1所示的数据项构成。
(表0-1)
首先编写一段代码如下:
package cn.lyx.jvm;
public class TestClass {
private int m;
public int inc(){
return m+1;
}
}
进到TestClass.java 文件所在目录,然后用 javac 编译生成 TestClass.class 文件。
javac .\TestClass.java
注!我用的jdk版本是 1.8
要研究class 文件的结构,得用一个能翻译class文件内容并让人看懂的编辑器,在此我用的是Winhex 十六进制编辑。
用Winhex 打开上一步生成的 TestClass.class 文件,内容如下图0-1:
(图0-1)
暂且不要对这横竖一推数字字母的东西感到排斥,等会慢慢来分析,会发现这些数字像迷宫一样有趣。
把上面的这张图结合表0-1,以另一种形式展现如下图0-2
(图0-2)
现在我们已经知道了Class 字节码文件的整体结构布局了。接下来我们从头到尾来分析每一个数据项的内容。
魔数:
所有的由Java编译器编译而成的class文件的前4个字节都是“0xCAFEBABE”,可以理解它是class 字节码文件的签名,就像你的身份证号一样。
次、主版本号:
JDK版本1.0.2中的Oracle Java虚拟机实现支持class45.0至45.3(含)的文件格式。JDK版本1.1.*支持class45.0到45.65535(含)的文件格式版本。对于 k≥2,JDK版本1.k支持class45.0到44 + k.0范围内的文件格式版本。
本例的主版本号0x34 换成十进制52, 52=44+8.0,所以该class 文件需要jdk 1.8以上版本运行。
常量池是class 字节码中比较复杂的内容。单独放在下文讨论。
参考:
https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4
《深入理解JAVA虚拟机.JVM高级特征与最佳实践》
http://blog.youkuaiyun.com/luanlouis/article/details/39892027