你知道Java字节码文件长什么样吗?

你知道字节码文件到底长什么样吗?

我们(指点赞的帅哥)知道,我们的java文件要编译才能使用,而编译的结果是.class文件。class文件是二进制文件,也就是0101010,那么我们今天的任务是读0101吗?当然不是,我们的任务是通过java自带的javap命令,把二进制文件变成我们看到懂的类型。

你知道Java字节码文件长什么样吗?

编写测试类

先写个简单的类,一个main方法一个add方法。

你知道Java字节码文件长什么样吗?

编译运行

你知道Java字节码文件长什么样吗?

当然我们今天的重头戏不是这个小Demo,我们要研究的是这个class文件,既然是二进制文件,我们的阅读起来肯定要有一定的手段

你知道Java字节码文件长什么样吗?

反编译class文件

使用 javap -c Hello 命令,我们得到这个一个结果。相对而言,比之前那个可读性强多了。

  • 我们看到了 public class Hello,public static void main 等类和方法的信息

  • 还有我们的lang包不用导包也能用,原来是Java帮我们加上了前缀

  • 我们之前那些变量都没了,变成了一堆JVM指令,当然我们现在是看不懂的。

你知道Java字节码文件长什么样吗?

我们去网上查查看这些指令是干什么的。

  • iload int类型变量到操作数栈

  • istore 将int类型值存入局部变量

  • iadd 执行int类型的加法

  • ireturn 从方法中返回int类型的数据

  • aconst_null 将null对象引用压入栈

  • invokevirtual 调度对象的实便方法

  • invokestatic 调用命名类中的静态方法

JVM指令分析

我简单解释了一些add方法

  • 将局部变量0和1也就是方法传入参数int a,int b压入到操作数栈
  • 将栈中的方法进行一波int的加法计算。
  • 计算结果再存入变量2,也就是sum
  • 将变量2再压入操作数栈,然后将操作数栈的内容返回出去。

你知道Java字节码文件长什么样吗?

实际上我们不需要定义局部变量2,也就是sum,这是去掉sum,直接return a+b 的JVM指令,我们看到我们的如return是直接返回操作数栈的内容。

你知道Java字节码文件长什么样吗?

main方法不讲了,大概就是一些参数传递,以及方法调用,等等。

总结

  • 使用javap -c 文件名 的方式可以查看class文件的JVM指令内容,文件名不要加后缀
  • java底层实际上对变量的命名都是以0,1,2,3来命名的,所以我们取的名字java不做考虑
  • 我们的加法运算实际上是一些入栈出栈操作,java底层很多地方时使用到栈这个数据结构

拓展

  • java -c 文件名 > 路径/文件名可以将控制台的结果保存到文件中,拓展名用txt即可。
  • 研究java底层的时候javap这个命令很重要,很多我们平时java文件看不到的信息记录在这些指令中
  • 对指令处于了解的水平即可,大概知道一下有哪些常用指令即可
  • 我们平时的哪些整数,浮点数类型自动转换,自动装箱等操作,你都可以通过javap的结果找打答案。