当前位置:网站首页>jvm 二之 栈帧内部结构
jvm 二之 栈帧内部结构
2022-08-02 06:29:00 【兮家小二】
栈帧内部结构
1、内存结构
在每一个方法 栈帧中都会有自己独立的,其中包括
- 1、局部变量表 (存放当前方法对应的局部变量);
- 2、操作数栈 (或表达式栈);
- 3、动态连接 (或指向运行时常量池的方法引用)
- 4、方法出口 (或方法正常退出或者异常退出的定义)
栈帧包含方法的所有信息
使用 javap -v Demo03.class
查看转成汇编后的源码
2、idea 分析插件
打开idea 中的settings > plugins 搜索 jclasslib
插件
重启后点击 view > 选择 show bytecode with jclasslib
查看分析
一、局部变量表
局部变量表中的变量只在 当前方法
调用中有效。
在方法执行时,虚拟机通过使用局部变量表完成参数值到参数变量列表的传递过程。
当方法调用结束后,随着方法栈帧的销毁,局部变量表也会随之销毁。
每一个方法都有一个局部变量表
1.1、Slot(变量槽–index)
public static void main(String[] args) {
String str = "mayikt";
int j = 20;
double d = 66.66;
boolean b = true;
}
如下: JVM会为局部变量表中每一个变量分配变量槽
- args 参数: 在 局部变量表中 slot 索引 0 的位置
- str 参数: 在 局部变量表中 slot 索引 1 的位置
- j 参数: 在 局部变量表中 slot 索引 2 的位置
- d 参数: 在 局部变量表中 slot 索引 3 的位置 (double 会占用两个槽位)
- b 参数: 在 局部变量表中 slot 索引 5 的位置
局部变量表最基本的存储单元就是变量槽。
- 32位以内的类型只占用一个slot (包括returnAddress类型),
- 64位的类型(long和double)占用两个slot。
- short,byte,boolean 等数据也占用一个变量槽,因为jvm会在存储时将上述变量转为int类型(变量槽是最基本存储单元,无法分割,只能整个使用)。
1.2、变量槽的复用
public static void mayikt002() {
int a = 0;
{
int b=30;
System.out.println("mayikt");
}
int c = 0;
}
此处原因就是JVM对变量槽有一个复用性为
- 变量b 使用了变量槽 1, 超出其作用域后不再生效,
- 变量c 发现变量槽 1 其作用域后超出, 直接占据了 b 的位置
1.3、变量槽中的 this
如果当前的方法是实例方法
或者是构造方法
则jvm默认会在局部变量表中创建 一个当前对象 this
, 存入在我们当前方法对应的局部表第0个位置
这样我们就可以在实例方法中 使用 this,静态方法不会。
public void mayikt() {
int j = 20;
}
变量槽中默认存在 this 变量
二、操作数栈
mian 调用 a, a 调用 b ,b 调用c , c调用 d, 方法会压入到栈空间中
而操作数栈是值变量的操作进行的压栈操作,从而可以执行相关 加减乘除 操作
2.1、基础操作 指令解析
当前代码
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 // 方法返回最后读取的变量槽数据
2.2、i++ 和 ++i 解析
i++
执行+1 前压入的栈数据, 栈顶数据是 0
++i
执行+1 后压入的栈数据, 栈顶数据是 1
2.3、栈溢出
StackOverflowError(栈溢出)
StackOverflowError代表的是,当栈深度超过虚拟机分配给线程的栈大小时就会出现此error
默认是有最大深度的, 常出现在递归调用中
2.4、方法出口
方法返回地址
2.5、动态链接
在操作数栈中找到被调用的子方法就是动态链接
动态链接: 每个栈帧都保存了 一个可以指向当前方法所在类的 运行时常量池,
目的是: 当前方法中如果需要调用其他方法的时候, 能够从运行时常量池中找到对应的符号引用, 然后将符号引用转换为直接引用,然后就能直接调用对应方法, 这就是动态链接
三、常量池
什么是常量池(Constant Pool)
java经过编译后生成的.class文件,是Class文件的资源仓库。
常量池分类:
- 运行时常量池 ,jvm虚拟机在完成类装载操作后,将class文件中的常量池载入到内存中,并保存在元空间中,我们常说的常量池,就是指方法区中的运行时常量池
- 静态常量池 class文件的关键信息,
类和接口的全限定名
,字段的名称和描述符
,方法的名称和描述符
,以及被 final 修饰的常量值等,如数量值
字符串值
以及字面量(Literal)和符号引用(Symbolic References) ,如:类引用
字段引用
方法引用
- 静态常量池 class文件的关键信息,
- 字符串常量池 顾名思义,存放字符串, 如:
Strng
,StringBuffer
,StringBuffer
等,jdk7 之前 方法区
,JDK7 存放在堆中
,JDK 8
方法区改 元空间字符串常量池
还是存放在我们堆中
。
- 字符串常量池 顾名思义,存放字符串, 如:
元空间就是之前的方法区
边栏推荐
- 暑期总结(三)
- 正则表达式的理解学习
- 【暑期每日一题】洛谷 P3156 【深基15.例1】询问学号
- 【暑期每日一题】洛谷 P1551 亲戚
- MySQL driver jar package download -- nanny tutorial
- Wuhan 2022 organizing of the high-performance computing added new ecological development of high-performance computing
- 【暑期每日一题】洛谷 P1255 数楼梯
- 分离轴定理SAT凸多边形精确碰撞检测
- 文件上传漏洞(二)
- postgres 多个变量填充字符串,字串格式化
猜你喜欢
随机推荐
ue先视频教程后深入
MPLS的相关技术
实例030:回文数
SphereEx苗立尧:云原生架构下的Database Mesh研发实践
MySQL - Multi-table query and case detailed explanation
MySQL (3)
MySQL high-level statements (1)
Connection reset by peer 问题解析
享年94岁,图灵奖得主、计算复杂性理论先驱Juris Hartmanis逝世
Neo4j 中文开发者月刊 - 202207期
[21天学习挑战赛——内核笔记](一)——设备树的概述(硬件、目标、效果、文件类型)
HCIP 第二天
笔记本开机黑屏提示:ERROR 0199:System Security-Security password retry count exceeded
postgres 多个变量填充字符串,字串格式化
mysql 注入
(Part of it is not understood, and the notes are not completed) [Graph Theory] Difference Constraints
Unity Shader学习(七)纹理图像的简单使用
CAT1 4G+以太网开发板腾讯云手机微信小程序显示温度和下发控制
【红队】ATT&CK - 创建或修改系统进程实现持久化(更新ing)
结构体大小计算--结构体内存对齐