jvm 线程私有区

jvm从多线程角度看,分为线程共享区、线程私有区

而在线程私有区中有:程序计数器、方法栈区(包括虚拟机栈、本地方法栈)

程序计数器

较小的内存空间,当前线程执行的字节码的行号指示器;各线程之间独立存储,互不影响

jvm的多线程是通过cpu时间片轮转算法实现的,某个线程在执行过程中会因为时间片耗尽而被挂起,其他线程获得时间片开始执行。当被挂起的线程重新获取到
时间片,它要想从之前被挂起的地方开始执行,就需要知道之前执行到了哪里,在jvm中,通过程序计数器来记录字节码执行的位置。因此,程序计数器是具备线程隔离的特性,也就是说,每个线程工作时都有属于自己的独立计数器。

程序计数器的特点

1、线程隔离:每个线程都有自己的程序计数器
2.执行java方法时,程序计数器是有值的,且记录的是正在执行的字节码指令的地址
3.执行native本地方法时,程序计数器的值为空(Undefined)。因为native方法是java通过JNI直接调用本地C/C++库,可以近似的认为native方法相当于C/C++暴露给java的一个接口,java通过调用这个接口从而调用到C/C++方法。由于该方法是通过C/C++而不是java进行实现。那么自然无法产生相应的字节码,并且C/C++执行时的内存分配是由自己语言决定的,而不是由JVM决定的。
4.程序计数器占用内存很小,在进行JVM内存计算时,可以忽略不计。
5.程序计数器,是唯一一个在java虚拟机规范中没有规定任何OutOfMemoryError的区域。

方法栈区

线程在运行时,在执行每一个方法的时候都会打包成一个栈帧,然后将栈帧入栈,当方法执行完时,就会将该栈帧出栈。每个时刻正在执行的当前方法就是虚拟机栈顶的栈桢。方法的执行就对应着栈帧在虚拟机栈中入栈和出栈的过程。

栈的大小缺省为1M,可用参数 –Xss调整大小,例如-Xss256k

栈帧结构

栈帧中含有:局部变量表、操作数据栈、动态链接、返回地址

局部变量表:顾名思义就是局部变量的表,用于存放我们的局部变量的。首先它是一个32位的长度,主要存放我们的Java的八大基础数据类型,一般32位就可以存放下,如果是64位的就使用高低位占用两个也可以存放下,如果是局部的一些对象,比如我们的Object对象,我们只需要存放它的一个引用地址即可。
操作数据栈:存放我们方法执行的操作数的,它就是一个栈,先进后出的栈结构,操作数栈,就是用来操作的,操作的的元素可以是任意的java数据类型,所以我们知道一个方法刚刚开始的时候,这个方法的操作数栈就是空的,操作数栈运行方法是会一直运行入栈/出栈的操作
动态连接:Java语言特性多态(需要类加载、运行时才能确定具体的方法),动态特性(Groovy、JS、动态代理)
返回地址:正常返回(调用程序计数器中的地址作为返回)、异常的话(通过异常处理器表<非栈帧中的>来确定)