我们都知道java文件需要编译成class文件,然后jvm负责加载并运行class文件,那么字节码文件长什么样子?字节码又是怎么执行的?
javap是JDK自带的查看字节码的工具。
javap的使用方法如下:
$ javac Demo.java
$ javap -p -v Demo
javap命令打印的文件内容有时候过多,可以使用javap -p -v Demo >> Demo.javap
将内容追加至文本文件中,再用文本工具打开分析。
有时候class文件中没有生成LineNumberTable或LocalVariableTable,可以在编译时使用下面的参数强制生成:
LocalVariableTable就是栈帧中的局部变量表。
LineNumberTable描述源码行号与字节码行号(字节码偏移量)之间的对应关系,有了这些信息,在debug时,就能够获取到发生异常的源代码行号。
如果你不太习惯使用命令行的操作,还可以使用jclasslib,jclasslib是一个图形化的工具,能够更加直观的查看字节码中的内容。它还分门别类的对类中的各个部分进行了整理,非常的人性化。同时,它还提供了Idea的插件,你可以从plugins中搜索到它。
如果你在其中看不到一些诸如LocalVariableTable的信息,记得在编译代码的时候加上我们上面提到的这些参数。
jclasslib的下载地址:https://github.com/ingokegel/jclasslib
下面的java代码就是后面要分析的字节码对应的源文件:
public class Demo {
private int a = 1111;
static long C = 2222;
public long test(long num) {
long ret = this.a + num + C;
return ret;
}
public static void main(String[] args) {
new Demo().test(3333);
}
}
test方法同时使用了成员变量a、静态变量C,以及输入参数num。我们此时说的方法执行,内存其实就是在虚拟机栈上分配的。下面这些内容,就是test方法的字节码。
public long test(long);
descriptor: (J)J
flags: ACC_PUBLIC
Code:
stack=4, locals=5, args_size=2
0: aload_0
1: getfield #2 // Field a:I
4: i2l
5: lload_1
6: ladd
7: getstatic #3 // Field C:J
10: ladd
11: lstore_3
12: lload_3
13: lreturn
LineNumberTable:
line 7: 0
line 8: 12
说明:
把第1个引用型局部变量推到操作数栈,这里的意思是把this装载到了操作数栈中。
对于static方法,aload_0表示对方法的第一个参数的操作。
将指定对象的第2个实例域(Field)的值,压入栈顶。#2就是指的我们的成员变量a。
将栈顶int类型的数据转化为long类型,这里就涉及我们的隐式类型转换了。
将第一个局部变量入栈,也就是我们的参数num,这里的l表示long。
把栈顶两个long型数值出栈后相加,并将结果入栈。
根据偏移获取静态属性的值,并把这个值push到操作数栈上,也就是静态变量C。
再次执行ladd。
把栈顶long型数值存入第4个局部变量,一个long和double类型会占用2个slot。
这里为什么要把栈顶的变量存入局部变量表中,又取出来入栈呢,为什么会有这种多此一举的操作?原因就在于我们定义了ret变量。JVM不知道后面还会不会用到这个变量,所以只好傻瓜式的顺序执行。
为了看到差异,我们可以把代码稍微改动一下,直接返回:
public long test(long num) {
return this.a + num + C;
}
对应的字节码如下:
public long test(long);
descriptor: (J)J
flags: ACC_PUBLIC
Code:
stack=4, locals=3, args_size=2
0: aload_0
1: getfield #2 // Field a:I
4: i2l
5: lload_1
6: ladd
7: getstatic #3 // Field C:J
10: ladd
11: lreturn
LineNumberTable:
line 7: 0
将第3个局部变量入栈,也就是我们的参数num,这里的l表示long。
从当前方法返回long。
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://morris131.blog.csdn.net/article/details/107411679
内容来源于网络,如有侵权,请联系作者删除!