线程私有部分
程序计数器:指向当前线程正在执行的字节码指令的地址(行号)。
为什么需要程序计数器:
1、java时多线程的,线程需要来回切换。
2、确保多线程情况下程序的正常执行。
虚拟机栈:存储当前线程运行方法所需的数据、指令、返回地址。
一个方法一个栈帧
栈帧:
1. 局部变量表(32位的定长区块,2的32次方):
存储局部变量,例如:
this(成员)
Object(引用)
weixin(自定义的字符串)
zhifubao(自定义的字符串)
2. 操作数栈
- 与局部变量表一样,均以字长为单位的数组。不过局部变量表用的是索引,操作数栈是弹栈/压栈来访问。操作数栈可理解为java虚拟机栈中的一个用于计算的临时数据存储区。
- 存储的数据与局部变量表一致含int、long、float、double、reference、returnType,操作数栈中byte、short、char压栈前(bipush)会被转为int。
- 数据运算的地方,大多数指令都在操作数栈弹栈运算,然后结果压栈。
- java虚拟机栈是方法调用和执行的空间,每个方法会封装成一个栈帧压入占中。其中里面的操作数栈用于进行运算,当前线程只有当前执行的方法才会在操作数栈中调用指令(可见java虚拟机栈的指令主要取于操作数栈)。
- int类型在-1~5、-128~127、-32768~32767、-2147483648~2147483647范围分别对应的指令是iconst、bipush、sipush、ldc(这个就直接存在常量池了)
这部分copy自:原文链接:https://blog.csdn.net/qq_28666081/article/details/85269879
3. 动态链接:符号引用和直接引用在运行时进行解析和链接的过程。
一个方法调用另一个方法,或者一个类使用另一个类的成员变量时,需要知道其名字,符号引用就相当于名字,这些被调用者的名字就存放在Java字节码文件里(.class 文件)。名字是知道了,但是Java真正运行起来的时候,如何靠这个名字(符号引用)找到相应的类和方法。需要解析成相应的直接引用,利用直接引用来准确地找到。
4. 返回地址:
当一个方法被执行后,有两种方式退出这个方法。第一种方式是执行引擎遇到任意一个方法返回的字节码指令,这时候可能会有返回值传递给上层的方法调用者(调 用当前方法的的方法称为调用者),是否有返回值和返回值的类型将根据遇到何种方法返回指令来决定,这种退出方法方式称为正常完成出口(Normal Method Invocation Completion)。
另外一种退出方式是,在方法执行过程中遇到了异常,并且这个异常没有在方法体内得到处理,无论是Java虚拟机内部产生的异常,还是代码中使用 athrow字节码指令产生的异常,只要在本方法的异常表中没有搜索到匹配的异常处理器,就会导致方法退出,这种退出方式称为异常完成出口(Abrupt Method Invocation Completion)。一个方法使用异常完成出口的方式退出,是不会给它的调用者产生任何返回值的。
无论采用何种方式退出,在方法退出之前,都需要返回到方法被调用的位置,程序才能继续执行,方法返回时可能需要在栈帧中保存一些信息,用来帮助恢复它的上 层方法的执行状态。一般来说,方法正常退出时,调用者PC计数器的值就可以作为返回地址,栈帧中很可能会保存这个计数器值。而方法异常退出时,返回地址是要通过异常处理器来确定的,栈帧中一般不会保存这部分信息。
方法退出的过程实际上等同于把当前栈帧出栈,因此退出时可能执行的操作有:恢复上层方法的局部变量表和操作数栈,把返回值(如果有的话)压入调用都栈帧的操作数栈中,调用PC计数器的值以指向方法调用指令后面的一条指令等。
本地方法栈