JVM-虚拟机栈(局部变量表)
2023-06-13 09:17:35 时间
1. 局部变量表
2.1 局部变量表介绍
- 局部变量表:Local Variables,也被称之为局部变量数组或本地变量表
- 定义为一个数字数组,主要用于存储方法参数和定义在方法体内的局部变量,这些数据类型包括各类基本数据类型、对象引用(reference),以及 returnAddress(返回值) 类型。
- 由于局部变量表是建立在线程的栈上,是线程的私有数据,因此不存在数据安全问题
- 局部变量表所需的容量大小是在编译期确定下来的,并保存在方法的Code属性的maximum local variables数据项中。在方法运行期间是不会改变局部变量表的大小的。
- 方法嵌套调用的次数由栈的大小决定。一般来说,栈越大,方法嵌套调用次数越多。
- 对一个函数而言,它的参数和局部变量越多,使得局部变量表膨胀,它的栈帧就越大,以满足方法调用所需传递的信息增大的需求。
- 进而函数调用就会占用更多的栈空间,导致其嵌套调用次数就会减少。
- 局部变量表中的变量只在当前方法调用中有效。
- 在方法执行时,虚拟机通过使用局部变量表完成参数值到参数变量列表的传递过程。
- 当方法调用结束后,随着方法栈帧的销毁,局部变量表也会随之销毁。
举例说明:局部变量表所需的容量大小是在编译期确定下来的
public class LocalVariablesTest {
private int count = 0;
public static void main(String[] args) {
LocalVariablesTest test = new LocalVariablesTest();
int num = 10;
test.test1();
}
public void test1() {
Date date = new Date();
String name1 = "baidu.com";
String info = test2(date, name1);
System.out.println(date + name1);
}
public String test2(Date dateP, String name2) {
dateP = null;
name2 = "xiexu";
double weight = 185.5;//占据两个slot
char gender = '男';
return dateP + name2;
}
}
反编译后,可得结论:
- 在编译期间,局部变量的个数、每个局部变量的大小都已经被记录下来
- 所以局部变量表所需的容量大小是在编译期确定下来的
- 利用 JClassLib 也可以查看局部变量的个数
JClassLib 参数详解
1.2 关于 Slot 的理解
- 参数值的存放总是从局部变量数组索引 0 的位置开始,到数组长度-1的索引结束。
- 局部变量表,最基本的存储单元是Slot(变量槽)
- 局部变量表中存放编译期可知的各种基本数据类型(8种),引用类型(reference),returnAddress类型的变量。
- 在局部变量表里,32位以内的类型只占用一个slot(包括 引用类型、returnAddress类型),64位的类型(long和double)占用两个slot。
- byte、short、char 在存储前被转换为int,boolean 也被转换为int,0 表示false,非0 表示true
- long 和 double 则占据两个Slot
- JVM会为局部变量表中的每一个Slot都分配一个访问索引,通过这个索引即可成功访问到局部变量表中指定的局部变量值
- 当一个实例方法被调用的时候,它的方法参数和方法体内部定义的局部变量将会按照顺序被复制到局部变量表中的每一个slot上
- 如果需要访问局部变量表中一个64bit的局部变量值时,只需要使用前一个索引即可。(比如:访问long或double类型变量)
- 如果当前帧是由构造方法或者实例方法(非静态方法) 创建的,那么该对象引用this 将会存放在index为0 的slot处,其余的参数按照参数表顺序继续排列。
在构造器以及实例方法中,对象引用this 都会存放在索引为0的位置
//构造器
public LocalVariablesTest() {
this.count = 1;
}
//实例方法
public void test1() {
Date date = new Date();
String name1 = "baidu.com";
test2(date, name1);
System.out.println(date + name1);
}
64位的类型(long和double)占用两个slot
public String test2(Date dateP, String name2) {
dateP = null;
name2 = "xiexu";
double weight = 185.5; //占据两个slot
char gender = '男';
return dateP + name2;
}
可以看到,weight为double类型,索引从3直接跳到5,说明double占据两个slot
static方法无法调用this
public static void testStatic() {
LocalVariablesTest test = new LocalVariablesTest();
Date date = new Date();
int count = 10;
System.out.println(count);
//因为this变量不存在于该静态方法的局部变量表中!!!
// System.out.println(this.count);
}
1.3 Slot 的重复利用
栈帧中的局部变量表中的槽位是可以重用的,如果一个局部变量出了其作用域,那么在其作用域之后声明新的局部变量就很有可能会复用过期局部变量的槽位,从而达到节省资源的目的。
public void test4() {
int a = 0;
{
int b = 0;
b = a + 1;
}
//变量c使用 之前已经销毁的变量b占据的slot的位置
int c = a + 1;
}
可以看到,局部变量c 重用了 局部变量b 的slot位置
相关文章
- jvm面试题2021_jvm运行原理及调优面试题
- 来聊聊 OpenJDK 和 JVM 虚拟机
- 究竟什么是Java虚拟机(JVM)?
- JVM面试题详解
- Java虚拟机(JVM)-- Dump内存快照
- 别再背新生代老年代了,这篇文章终于把JVM的GC讲清楚了
- 《快学BigData》--JVM 总结(20)
- JVM学习- - -虚拟机栈详解
- 一文学会JVM垃圾回收器详解:串行回收,新生代内存管理内存分配
- 【Java 虚拟机原理】栈帧 | 局部变量表 | 操作数栈 | 方法出口 | JVM 指令逐条解析
- 【Java 虚拟机原理】垃圾回收算法 ( 设置 JVM 命令参数输出 GC 日志 | GC 日志输出示例 | GC 日志分析 )
- JVM 内存问题排查:从入门到精通 | 极客时间
- Java 优化的5个方面是:架构、SQL、性能、接口和 JVM
- Jvm虚拟机结构与机制详解程序员
- JVM类加载机制详解编程语言
- [四] java虚拟机JVM编译器编译代码简介 字节码指令实例 代码到底编译成了什么形式详解编程语言
- 如何在Linux上查看JVM运行信息(Linux查看jvm)
- JVM监控在Linux系统上的应用(jvm监控 linux)
- 如何在Linux下修改JVM参数配置(linux修改jvm参数)
- 解锁Oracle指引你的JVM下载之旅(jvm下载oracle)
- Java虚拟机JVM性能优化(一):JVM知识总结