带你手撕Java虚拟机栈(手把手实战)
程序员文章站
2022-07-15 14:50:18
...
Java虚拟机栈
Java方法执行的内存模型
一个栈帧就是对应一个方法被执行的过程,入栈、出栈分别对应方法加载、执行结束
让我们来个????
首先,创建一个类
把它编译为class,再把它javap反编译回来,脱裤子放屁就为了看两行字节码,也是不容易
qiyankaideMacBook-Pro:study qiyankai$ javap -verbose Demo.class
Classfile /Users/qiyankai/Desktop/project/foodie-dev/foodie-dev-study/target/classes/study/Demo.class
Last modified 2020-5-26; size 405 bytes
MD5 checksum e3064bf4c80f943fa3031fe07f62d00e
Compiled from "Demo.java"
public class study.Demo
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #3.#20 // java/lang/Object."<init>":()V
#2 = Class #21 // study/Demo
#3 = Class #22 // java/lang/Object
#4 = Utf8 <init>
#5 = Utf8 ()V
#6 = Utf8 Code
#7 = Utf8 LineNumberTable
#8 = Utf8 LocalVariableTable
#9 = Utf8 this
#10 = Utf8 Lstudy/Demo;
#11 = Utf8 add
#12 = Utf8 (II)I
#13 = Utf8 a
#14 = Utf8 I
#15 = Utf8 b
#16 = Utf8 c
#17 = Utf8 MethodParameters
#18 = Utf8 SourceFile
#19 = Utf8 Demo.java
#20 = NameAndType #4:#5 // "<init>":()V
#21 = Utf8 study/Demo
#22 = Utf8 java/lang/Object
{
public study.Demo();
descriptor: ()V
flags: 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 Lstudy/Demo;
public static int add(int, int);
descriptor: (II)I
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=3, args_size=2
0: iconst_0
1: istore_2
2: iload_0
3: iload_1
4: iadd
5: istore_2
6: iload_2
7: ireturn
LineNumberTable:
line 5: 0
line 6: 2
line 7: 6
LocalVariableTable:
Start Length Slot Name Signature
0 8 0 a I
0 8 1 b I
2 6 2 c I
MethodParameters:
Name Flags
a
b
}
SourceFile: "Demo.java"
javap -verbose 口语化反编译
public static int add(int, int);
descriptor: (II)I
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=3, args_size=2
0: iconst_0
1: istore_2
2: iload_0
3: iload_1
4: iadd
5: istore_2
6: iload_2
7: ireturn
LineNumberTable:
line 5: 0
line 6: 2
line 7: 6
LocalVariableTable:
Start Length Slot Name Signature
0 8 0 a I
0 8 1 b I
2 6 2 c I
MethodParameters:
Name Flags
a
b
执行add(1,2)
我的图有点模糊,凑活看吧
- iconst_0:1,2进入局部变量表,操作数栈0,程序计数器0
- istore_2:pop操作数栈,放到局部变量表第2位(从0开始算),程序计数器1
- iload_0:加载局部变量表0位到,操作数栈
- iload_1:加载局部变量表1位到,操作数栈
- iadd:操作数栈值相加
- istore_2:pop操作数栈,放到局部变量表第2位
- iload_2:加载局部变量表2位到,操作数栈
- ireturn:返回操作数栈的值
我真的尽力了,我觉得聪明的大家肯定能听懂!
下来我们讲讲递归吧
递归为什么会引发java.lang.*Error异常
因为执行一个方法,会增加一个栈帧,保存当前栈帧,一致一直增加
压栈、压栈、压栈、压栈、boom!
上一篇: CSS多行文字溢出省略号表示
下一篇: CSS 单/多行文本溢出样式
推荐阅读