目录
5.3、HotSpot在1.7版本以前和1.7版本,1.7版本后都有变化
一、前言
我们要明白所说的Java内存就是JVM内存,Java代码是运行在Java虚拟机之上的,由Java虚拟机通过解释执行(解释器)或编译执行(JIT编译器)来完成,故Java内存模型,也就是指Java虚拟机的运行时内存模型。
二、具体介绍
1、程序计数器
1.1、概念
程序计数器( ProgramCounterRegister)是一块较小的内存空间,它可以看作是当前线程所执行的Java字节码的行号指示器。可以理解为程序计数器在这里记住的JVM下一条指令的执行地址,当第一条指令执行完,那么解释器就会到程序计数器中取寻找下一条指令。在物理上来讲的话 程序计数器是通过寄存器来实现的。
1.2、特点
1.2.1、如果当前线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址,如果正在执行的是Native方法,这个计数器值则为空(Undefined,并且所有的CPU 都有一个PC 每执行一条指令PC都会自增 因此PC存储了指向下一条要被执行的指令。
1.2.2、线程是私有的
每个线程都有自己的程序计数器,来记录自己线程执行到的指令,各条线程之间计数器互不影响,独立存储这就是我们所说的线程是私有的,并且当某一个线程执行完成之后,它会从自己的程序计数器中取出要执行的下一条指令。
1.2.3、程序计数器 不存在内存溢出 OOM(OutOfMemoryError),因为程序计数器是很小的空间 ,可以把它看成字节码行号的指示器。
2、Java的虚拟机栈
2.1、概念
Java中每个线程在运行的时候都需要划分内存空间,虚拟机栈是指每个线程在运行时需要的内存空间,所以说每条线程中都会存在一个虚拟机栈,而虚拟机栈中的每一块空间都是一个栈帧,一个栈帧对应着一次方法的调用。且每一个栈帧都用于存储局部变量表、操作数栈、动态链接、方法返回地址、额外的信息等。
2.2、局部变量表
局部变量表主要存放的数据:
2.2.1、编译期的的各种基本数据类型(boolean、byte、char、short、int、float、long、double)
2.2.2、对象的引用 reference 类型 引用指针
2.2.3、ReturnAddress 类型 -----指向了一条字节码指令
其中64位的long double 会占用两个局部变量的空间(slot) 其余的类型都只占用1个slot。局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。
2.2.4、异常
如果线程请求的栈的深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;虚拟机的栈是可以进行动态扩展的,当扩展时申请不到足够的内存时,将抛出OutOfMemoryError异常。
2.3、操作数栈
2.3.1、概念
操作数栈类似于局部变量表, 操作栈也是后进先出,操作数栈的最大深度 class文件中的Code属性max_stacks 数据项。
2.3.2、操作数栈存储的类型
32位的数据类型 栈容量为1
64位的数据类型 栈容量为2
栈容量的单位 ----字宽
对32位的虚拟机 一个字宽是 4个字节
对64位的虚拟机 一个字宽是8个字节<