JVM学习(一)非线程共享-运行时数据区域

  那么没有错,我码仔也要开始周志明的JVM之路,整本书模块很多,只取需要的部分进行学习,如果其中有什么错误的理解,请各位指出,让我能认识到不足的地方,谢谢。
Tip: 始终追寻第一遍是记忆,第二遍是修改,第三遍是回顾加修改

JVM运行时数据区

本部分采用是否线程隔离/线程共享来描述这个数据区可能会比较切实点。
当然也有切分成数据流与指令流来描述,如下
JVM学习(一)非线程共享-运行时数据区域

但是我采用的是这个↓
JVM学习(一)非线程共享-运行时数据区域


一、程序计数器(Program Counter Register)

简略: 用于指定当前字节码解析行号的指示器(在挂起的时候记录运行的行号、地址,唤醒时恢复执行到的行号、地址)

  根据多线程的CUP时间片分配机制,我们可以了解到,同一时间一个处理器只会执行一个条线程中的指令
  同时以防线程间切换CPU后不能恢复到原来的位置,因此每条线程都需要一个独立的程序计数器,属于线程隔离(线程私有的内存)。

tips:唯一一个虚拟机规范中没有规定OutOfMemoryError\color{red}{OutOfMemoryError}情况的内存区域


二、虚拟机栈

也归属线程私有,存储当前线程运行方法所需数据、地址及指令

这里提点到一个词:栈帧(Stack Frame)

  文字描述可能比较枯燥:这里以方法Helloworld为例子
(每一个方法从调用直到执行完成的过程,对应着一个栈帧在虚拟机中从入栈到出站的过程)

JVM学习(一)非线程共享-运行时数据区域

局部变量表与操作数栈

参考方法用于展示

public class hi{
	public static int fine(int i){
		int c = i;
		return c++;
	}
}

JVM学习(一)非线程共享-运行时数据区域

上述过程:
0 - 传入变量压入到操作数栈
1 - 弹出栈顶元素,存放到局部变量第一个位置
2 - 将局部变量第一个加载到操作数栈
3 - 栈顶局部变量做自增操作
6 - 从当前方法返回int

操作数栈与局部变量(基本类型)的操作:
①将一个局部变量加载到操纵栈的指令包括:iload_、lload…

②将一个数值从操作数栈存储到局部变量表的指令包括:istore_、lstore…
(这里说到了指令集的方法,也是另一种说归属于指令流划分的原因)

如果是引用对象: 会指向Heap(堆)

一个局部变量表的单位:占用32位的存储空间(一个存储单位称之为slot,槽),long和double需要2个连续的局部变量单位

动态连接

类似一个接口,实现它的方法,是要动态找它的实现类,并获取其中要执行的方法,这也属于动态链接的一个部分

tip: 本内存区域允许异常:


1、线程方法请求栈深度超过虚拟机所允许深度(通常类递归会出现),则会抛出StackOverflowError\color{red}{StackOverflowError}异常


2、如果虚拟机栈动态拓展(通常两种方式:Segmented stack和Stack copying),如果拓展的时候无法申请到足够的内存,则会抛出异常OutOfMemoryError\color{red}{OutOfMemoryError}

本地方法栈

与虚拟机栈发挥作用相似,具体实现交由虚拟机实现,不限制语言不拓展这个方向,不是主要关心的内容,暂时来讲