在每一个方法 栈帧中都会有自己独立的,其中包括
栈帧包含方法的所有信息
使用 javap -v Demo03.class 查看转成汇编后的源码

打开idea 中的settings > plugins 搜索 jclasslib 插件
重启后点击 view > 选择 show bytecode with jclasslib

查看分析

局部变量表中的变量只在 当前方法 调用中有效。
在方法执行时,虚拟机通过使用局部变量表完成参数值到参数变量列表的传递过程。
当方法调用结束后,随着方法栈帧的销毁,局部变量表也会随之销毁。
每一个方法都有一个局部变量表
public static void main(String[] args) {
String str = "mayikt";
int j = 20;
double d = 66.66;
boolean b = true;
}
如下: JVM会为局部变量表中每一个变量分配变量槽

局部变量表最基本的存储单元就是变量槽。
public static void mayikt002() {
int a = 0;
{
int b=30;
System.out.println("mayikt");
}
int c = 0;
}
此处原因就是JVM对变量槽有一个复用性为

如果当前的方法是实例方法或者是构造方法 则jvm默认会在局部变量表中创建 一个
当前对象 this , 存入在我们当前方法对应的局部表第0个位置 这样我们就可以在实例方法中 使用 this,静态方法不会。
public void mayikt() {
int j = 20;
}
变量槽中默认存在 this 变量

mian 调用 a, a 调用 b ,b 调用c , c调用 d, 方法会压入到栈空间中
而操作数栈是值变量的操作进行的压栈操作,从而可以执行相关 加减乘除 操作
当前代码
public int compute() {
int a = 10;
int b = 20;
int c = (a + b) * 10;
return c;
}
转汇编后的代码 , javap -v xxxx.class

0: bipush 10 // 将一个8位带符号整数压入栈
2: istore_1 // 变量槽 1 a 存入 10
3: bipush 20 // 将一个8位带符号整数压入栈
5: istore_2 // 变量槽 2 b 存入 20
6: iload_1 // 获取槽1 变量a=10;
7: iload_2 // 获取槽2 变量a=20;
8: iadd // i执行int类型的加法 10+20=30
9: bipush 10 // 将一个8位带符号整数压入栈 10
11: imul // imul 执行int类型的乘法 30*10=300
12: istore_3 // 变量槽3 c存入计算结果 300
13: iload_3 // 获取槽3 变量c=300;
14: ireturn // 方法返回最后读取的变量槽数据
i++
执行+1 前压入的栈数据, 栈顶数据是 0

++i
执行+1 后压入的栈数据, 栈顶数据是 1

StackOverflowError(栈溢出)
StackOverflowError代表的是,当栈深度超过虚拟机分配给线程的栈大小时就会出现此error
默认是有最大深度的, 常出现在递归调用中
方法返回地址
在操作数栈中找到被调用的子方法就是动态链接
动态链接: 每个栈帧都保存了 一个可以指向当前方法所在类的 运行时常量池,
目的是: 当前方法中如果需要调用其他方法的时候, 能够从运行时常量池中找到对应的符号引用, 然后将符号引用转换为直接引用,然后就能直接调用对应方法, 这就是动态链接
什么是常量池(Constant Pool)
java经过编译后生成的.class文件,是Class文件的资源仓库。
类和接口的全限定名,字段的名称和描述符,方法的名称和描述符,以及被 final 修饰的常量值等,如 数量值 字符串值 以及字面量(Literal)和符号引用(Symbolic References) ,如: 类引用 字段引用 方法引用Strng, StringBuffer ,StringBuffer 等, jdk7 之前 方法区,JDK7 存放在堆中 , JDK 8方法区改 元空间 字符串常量池还是存放在我们堆中。
元空间就是之前的方法区
