深入理解JVM虚拟机 第二章 java内存区域与内存溢出异常 2.2 运行时数据区
2.2 运行时数据区
1 概述
运行时数据区
2.2.1 程序计数器
1.pc寄存器(程序计数器)
可以看做(当前线程的)字节码的行号指示器(.class文件的行号,记住指令运行到哪了)
每一个java线程都有自己的pc寄存器。
如果该方法是nativa,那么pc寄存器得值是undefined,如果不是native的,那么pc寄存器就保存jvm正在执行的字节码指令地址。
程序计数器是唯一一块Java虚拟机规范中没有任何规定的OutOfMemoryError情况的区域;
字节码指令集,由操作码和操作数组成,.java文件编译后的.class就是操作数和操作码的集合
2.2.2 Java虚拟机栈
Java虚拟机栈:线程私有,这个栈和线程同时创建(生命周期与线程相同),用于存储栈帧;
是用来描述Java方法执行的内存模型,每个方法在执行时都会创建一个栈帧
void spin(){
int i ;
for (i = 0;i<100;i++){
....
}
}
这个方法中,
0,100两个常量存放在操作数栈
整形变量i存放在局部变量变量表中
栈帧
用于存储局部变量表,操作数栈,动态链接,方法出口等信息,每一个方法从被调用到执行完毕,都对应者一个栈帧在虚拟机栈中入栈到出栈的过程。
1 局部变量表
每个栈帧都包含一组变量列表,称之为局部变量表,用于存储 方法的形参和方法内部定义的变量(局部变量)(这些变量也包括引用类型),和returnAddress(返回地址类型);
这些参数和局部变量都是编译期可知的。
注意,引用类型的局部变量也会存储在局部变量表中,只不过存储的是引用类型的地址。
jvm使用局部变量表 完成方法调用时方法的传递
通过索引来访问,第0个局部变量一定用来存储该实例方法所在对象的引用(this),static修饰的方法除外;
系统不会为局部变量赋予初始值(实例变量和类变量会被赋予初始值)。也就是说局部变量表不存在类变量那样的准备阶段。
类变量,static修饰的变量
Solt
局部变量表的容量以变量槽(Slot)为最小单位,其中64位的double和long占用2个连续的solt,访问时访问索引小的solt,
对于byte、short以及char类型的值在局部变量表之前,会被转换为int。
因为方法的参数和局部变量,在编译器就已经确定了,所以局部变量表的空间大小在编译器就已经确定。
2 操作数栈
大小由编译器期决定
标准的栈运作 ,通过出栈/压栈来访问
操作数栈存储 常量和变量值,
jvm把局部变量表中或者对象实例中 复制常量和变量值到操作数栈中,jvm也从操作数栈中取出数据和操作数据以及把操作结果重新入栈。
虚拟机在操作数栈中存储数据的方式和在局部变量区中是一样的,对于byte、short以及char类型的值在压入到操作数栈之前,也会被转换为int。
3 动态链接
一个引用,(当前方法所在类型的)运行时常量池的引用
好文推荐
https://blog.csdn.net/a616413086/article/details/51272309
https://zhuanlan.zhihu.com/p/45354152