Java栈——操作数栈
文章目录Java栈——操作数栈Java栈——操作数栈先明确一个概念,Java栈(虚拟机栈)内存储的是栈帧,多个栈帧组成了一个虚拟机栈。栈帧是JVM进行方法调用使用的数据结构。栈帧内保存包含有操作数栈。操作数栈保存了方法执行过程中各指令的操作数。看下边代码:public class Test1 {public int add(int a, int b) {int c = a + b;return c
·
文章目录
Java栈——操作数栈
先明确一个概念,Java栈(虚拟机栈)内存储的是栈帧,多个栈帧组成了一个虚拟机栈。栈帧是JVM进行方法调用使用的数据结构。
栈帧内保存包含有操作数栈。操作数栈保存了方法执行过程中各指令的操作数。
看下边代码:
public class Test1 {
public int add(int a, int b) {
int c = a + b;
return c;
}
public static void main(String[] args) {
Test1 test1 = new Test1();
test1.add(1,1);
}
}
对应的字节码文件:
Classfile <Path to /com/sanren1024/jvm/Test1.class>
Last modified ...; size 578 bytes
SHA-256 checksum fd3bf061ff99b334ba84db7afd21242589b527334dee24ff7d0410c0927aa9be
Compiled from "Test1.java"
public class com.sanren1024.jvm.Test1
minor version: 0
major version: 57
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #7 // com/sanren1024/jvm/Test1
super_class: #2 // java/lang/Object
interfaces: 0, fields: 0, methods: 3, attributes: 1
Constant pool:
#1 = Methodref #2.#3 // java/lang/Object."<init>":()V
#2 = Class #4 // java/lang/Object
#3 = NameAndType #5:#6 // "<init>":()V
#4 = Utf8 java/lang/Object
#5 = Utf8 <init>
#6 = Utf8 ()V
#7 = Class #8 // com/sanren1024/jvm/Test1
#8 = Utf8 com/sanren1024/jvm/Test1
#9 = Methodref #7.#3 // com/sanren1024/jvm/Test1."<init>":()V
#10 = Methodref #7.#11 // com/sanren1024/jvm/Test1.add:(II)I
#11 = NameAndType #12:#13 // add:(II)I
#12 = Utf8 add
#13 = Utf8 (II)I
#14 = Utf8 Code
#15 = Utf8 LineNumberTable
#16 = Utf8 LocalVariableTable
#17 = Utf8 this
#18 = Utf8 Lcom/sanren1024/jvm/Test1;
#19 = Utf8 a
#20 = Utf8 I
#21 = Utf8 b
#22 = Utf8 c
#23 = Utf8 main
#24 = Utf8 ([Ljava/lang/String;)V
#25 = Utf8 args
#26 = Utf8 [Ljava/lang/String;
#27 = Utf8 test1
#28 = Utf8 SourceFile
#29 = Utf8 Test1.java
{
public com.sanren1024.jvm.Test1();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 3: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/sanren1024/jvm/Test1;
public int add(int, int);
descriptor: (II)I
flags: (0x0001) ACC_PUBLIC
Code:
stack=2, locals=4, args_size=3
0: iload_1
1: iload_2
2: iadd
3: istore_3
4: iload_3
5: ireturn
LineNumberTable:
line 6: 0
line 7: 4
LocalVariableTable:
Start Length Slot Name Signature
0 6 0 this Lcom/sanren1024/jvm/Test1;
0 6 1 a I
0 6 2 b I
4 2 3 c I
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=2, args_size=1
0: new #7 // class com/sanren1024/jvm/Test1
3: dup
4: invokespecial #9 // Method "<init>":()V
7: astore_1
8: aload_1
9: iconst_1
10: iconst_1
11: invokevirtual #10 // Method add:(II)I
14: pop
15: return
LineNumberTable:
line 11: 0
line 12: 8
line 13: 15
LocalVariableTable:
Start Length Slot Name Signature
0 16 0 args [Ljava/lang/String;
8 8 1 test1 Lcom/sanren1024/jvm/Test1;
}
SourceFile: "Test1.java"
看到局部变量表上,slot1是test1实例。源码文件中调用了 test1.add(1,1) 方法,可以查看字节码的指令的执行。
public int add(int, int);
descriptor: (II)I
flags: (0x0001) ACC_PUBLIC
Code:
stack=2, locals=4, args_size=3
0: iload_1 // 加载slot1操作数 slot1: a=1
1: iload_2 // 加载slot2操作数 slot2: a=1
2: iadd // 执行add操作 结果:2
3: istore_3 // 保存结果slot3 slot3:c=2
4: iload_3 // 加载slot3
5: ireturn // 返回
LineNumberTable:
line 6: 0
line 7: 4
LocalVariableTable:
Start Length Slot Name Signature
0 6 0 this Lcom/sanren1024/jvm/Test1;
0 6 1 a I
0 6 2 b I
4 2 3 c I
对应的操作数栈内表现:
c(2)
2
1(b)
1(a)
最后返回,就返回栈顶的值。
在JVM的优化中,有时候,几个栈帧会共用一个操作数栈,来节约内存。
更多推荐
已为社区贡献6条内容
所有评论(0)