JVM — javap
什么是Java字节码指令?简而言之,Java字节码指令就是Java虚拟机能够听得懂、可执行的指令,可以说是Jvm层面的汇编语言,或者说是Java代码的最小执行单元
javac命令可以将源文件翻译成Jvm可以执行的指令
javap命令,它可以解析字节码,将字节码内部逻辑以可读的方式呈现出来
前置知识JVM字节码指令表(以下是本次文章会用到的指令)
iconst_m1 将int型的m1推送至栈顶
iload_m 将指定的第m个int型本地变量推送至栈顶
以上使用i来代表int
d:double,f:float
a:Reference,l:long
ps:当int 取值-1~5 采用iconst 指令,取值-128~127 采用bipush 指令,取值-32768~32767 采用sipush 指令,取值-2147483648~2147483647 采用ldc 指令
详细内容可以查看https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5
上一个Demo:
public class Demo {
public static void main(String[] args) {
int i = 11;
int j = 12;
int c = i + j;
System.out.println(c);
}
}
使用javap来分解一下
javap -verbose Demo.class > Demo.txt
打开Demo.txt,截取一部分
JVM执行字节码指令的时候基于栈结构的(先入后出)
我们重点看的是Code后面的
//常量池
Constant pool:
#1 = Methodref #5.#14 // java/lang/Object."<init>":()V
#2 = Fieldref #15.#16 // java/lang/System.out:Ljava/io/PrintStream;
#3 = Methodref #17.#18 // java/io/PrintStream.println:(I)V
#4 = Class #19 // Demo
#5 = Class #20 // java/lang/Object
#6 = Utf8 <init>
#7 = Utf8 ()V
......
{
public Demo();
descriptor: ()V
flags: ACC_PUBLIC
Code:
//操作数栈最大深度,本地变量表最大长度(64位操作系统为2其余为1),参数个数
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 7: 0
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
//字节码
Code:
stack=2, locals=4, args_size=1
0: bipush 11 //将11入栈
2: istore_1 //取出栈顶元素存进本地变量1
3: bipush 12 //将12入栈
5: istore_2 //取出栈顶元素存进本地变量2
6: iload_1 //把本地变量1入栈
7: iload_2 //把本地变量2入栈
8: iadd //把栈顶取两个元素进行加法,进行入栈
9: istore_3 //取出栈顶元素存进本地变量3
10: getstatic #2 //调用System.out // Field java/lang/System.out:Ljava/io/PrintStream;
13: iload_3 //把本地变量3入栈
14: invokevirtual #3//print语句 // Method java/io/PrintStream.println:(I)V
17: return //返回值
//行号表,第一个数字代表代码的行号,第二个数字代表字节码的行号
LineNumberTable:
line 9: 0
line 10: 3
line 11: 6
line 12: 10
line 13: 17
}