Java的.Class类文件结构分析
序言:JVM 把我们的.java文件编译为.Class文件,本文只要分析
①反汇编Class文件后对应的java字节码指令
②Class文件的文件结构(使用工具WinHex查看)
第一步:
我们先写一个简单的.java程序(本文已Test02.java为例进行简单分析)
Test02.java代码如何:
运行Test02.java后得到.class文件
第二步:
使用javap -c Test02.class>Test.txt命令把.class文件反汇编后的内容写入到Test.txt文件
接下来查看test.txt内容
**第三步:**分析对照java的原生程序分析java的字节码指令(把写的代码和字节码指令对照看看JVM的执行器是如何执行我们写的java代码)
``具体分析如图
具体代码如下:
①java文件代码
public class Test02 {
public static void main(String[] args) {
// TODO Auto-generated method stub
int m=test();
System.out.println(m);
}
public static int test() {
int m=0;
for (int i= 0; i<=10; i++) {
m=m+i;
}
if (m>10?true:false) {
return m;
}else {
return 0;
}
}
}
②java字节码代码
Compiled from "Test02.java"
public class com.test.Test02 {
public com.test.Test02();
Code:
0: aload_0 //第0项常量默认是空出来的
1: invokespecial #8 // Method java/lang/Object."<init>":()V 在super的class文件中调用main方法
4: return
public static void main(java.lang.String[]);
Code:
0: invokestatic #16 //调用test方法
3: istore_1 //把返回的值存入m的值送入栈
4: getstatic #20 // 调用Java的打印输出流
7: iload_1 //获得栈中的值(对应为main方法中m的值)
8: invokevirtual #26 //输出打印出来
11: return
public static int test();
Code:
0: iconst_0 //把0放入虚拟机栈栈顶
1: istore_0 //把栈顶0赋给变量m
2: iconst_0 //把0放入虚拟机栈栈顶
3: istore_1 //把栈顶0赋给变量i
4: goto 14 //此步开始for循环
7: iload_0 //把变量m的值放入虚拟机栈顶
8: iload_1 //把变量i的值放入虚拟机栈顶
9: iadd //将栈顶的第一个值和第二个值相加得到结果存入栈顶
10: istore_0 //把虚拟机栈顶的值付给第一个变量m(m的值为m+i的和)
11: iinc 1, 1 //i自增
14: iload_1 //把m推送进虚拟机栈(m为0~10的和)
15: bipush 10 //把10推送进虚拟机栈
17: if_icmple 7 //比较虚拟机栈顶的两个int的大小,小于等于0跳转
20: iload_0 //把m的值送入虚拟机栈顶
21: bipush 10 //把10推送进虚拟机栈
23: if_icmple 28 //比较虚拟机栈顶的两个int的大小,小于等于0跳转
26: iload_0 //iload_0的值为所求的和
27: ireturn //返回和
28: iconst_0 //iconst_0的值为0
29: ireturn //返回0
}
**第四步:我们将分析Class文件的结构(JVM是如何识别Class文件的)
**
.class是一个二进制的文件,二进制文件里并没有我们熟知的高级编程语言代码,所以接下来我们将走入计算机二进制的世界,Winhex将以16进制的形式展现出我们写的java程序经过编译后的Class文件,我们也主要分析Class (16进制)的结构 如图
如何去理解这一大推看不懂的十六进制数呢?这就需要理解Class的类文件结构
①Class的文件标识(标准叫法:魔数)
它是一个4字节数从文件开头算起0xCAFEBABE
②紧接着魔数后的4个字节为Class文件的版本号
③版本号过后就是常量池(Class文件结构中最复杂的部分)
前2个字节为常量池的数量
由上图可知值为0x28对应的十进制为40,常量池的数量=值-1,所以常量池数量为39
由此以后开始常量池的分析为了节约空间我直接给出常量池的截图,具体可以参考《深入理解JVM虚拟机》这本书
④接下来为访问标志(占2个字节)0x0021
⑤类索引,父类索引,接口索引集合
这三个各占2个字节
⑥字段表
⑦方法表
⑧属性表(方法表结束位2F以下 的内容为属性表内容)