title: Java字节码(一):深度分析Class类文件
date: 2019-03-27 15:58:04
categories:
- Java虚拟机
tags: - Java字节码
引言
我们知道,java
是一个跟平台无关性的编程语言,而平台无关性的基础就是虚拟机与字节码存储格式。Java
虚拟机不和包括java
语言在内的任何语言绑定,它只认Class
文件(kotlin
、scala
等皆可在jvm
上运行)。Class
文件中包含了一个Java
程序的指令集和符号集以及其他信息,编译器严格按照规范来将Java
程序编译为字节码。在这儿,我们分析下Class
文件的数据结构。
Class类文件结构
Class
文件是以8位字节为基础的二进制流文件,其中没有间隔,在文件中只保留了必要的数据,节省了大量的空间。在Class
字节码中有两种数据类型:
- 字节数据直接量:这是基本的数据类型。共细分为
u1
、u2
、u4
、u8
四种,分别代表连续的1
个字节、4
个字节、8
个字节组成的整体数据。 - 表(数组):表是由多个基本数据或其他表,按照既定顺序组成的大的数据集合。表是有结构的,它的结构体现在:组成表的成分所在的位置和顺序都是已经严格定义好的。
如下图所示,Class
文件中字节码按一下顺序进行排列。
我们通过最简单的一个程序,来示例讲解Class
文件结构。
public class MyTest1 {
private int a = 1;
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
}
使用16进制工具(winHex
)打开MyTest1.class
文件,16进制字节码中,一个数字或字母占4位,两个数字或字母代表一个字节。
使用javap -verbose
命令分析一个字节码文件时,将会分析该字节码文件的魔数、版本号、常量池、类信息、类的构造方法、类中的构造方法、类中的方法信息、类变量与成员变量等信息。
魔数(4个字节)
所有的.class
字节码文件的前4个字节都是魔数,魔数值是一固定值:0xCAFEBABE
。 是用以Java
虚拟机确定class
文件的标志。很多文件格式都采用了魔数来进行文件的身份标识,比如jpg
。选择在文件内容头部使用魔数而不用扩展名来进行文件的身份标识,主要是考虑了安全问题,因为扩展名易被修改。而魔数则可以由文件格式的制定者随意的指定,只要选择的魔数没有被广泛采用且不与其他魔数重复引起混淆就行。
版本号(2+2个字节)
.魔数之后的4个字节为版本信息,前两个字节表示minor version
(次版本号),后两个字节表示