JVM内存结构与内存模型

814 阅读5分钟

一、 Jvm内存结构

模块分解

1. 程序计数器(线程私有)

(1) 是什么?

    程序计数器是当前线程所执行的字节码的行号指示器。

(2) 作用?

    字节码解释器通过改变这个计算器的值来选择下一条需要执行的字节码指令,分支,循环,跳转,异常处理,线程恢复,如果执行的是Native方法,这个计算器的值则为空

2. Java虚拟机栈(线程私有)

(1) 是什么

    Java虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧,每个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。

(2) 组成

① 局部变量表

    存放了编译期可知的基本类型、对象引用类型和returnAddress类型(指向一条字节码指令的地址。即程序就是存储在方法区的字节码指令,而 returnAddress 类型的值就是指向特定指令内存地址的指针)

② 操作数栈

    操作数是一个后入先出栈,JVM所有的操作码都是对操作数栈上的数据进行操作,对于每一个方法的调用,JVM会建立一个操作数栈,以供计算使用。

    例如 a = b + c 的字节码执行过程中操作数栈以及局部变量表的变化如下图所示。

    局部变量表中存储着a、b、c 三个局部变量,首先将b和c分别入栈

③ 动态链接

    运行期间转化为直接引用,就称为动态链接。Class字节码的常量持中存有大量的符号引用,在运行期才将符号引用变成直接引用(也就是指向数据),可以是方法或者字段的引用。

④ 方法出口

    即本方法执行后下一步指令的地址,方法正常退出时,调用者PC计数器的值就可以作为返回地址,异常退出时,返回地址是要通过异常处理器来确定。

3. 本地方法栈(线程私有)

(1) 是什么?

    保存native方法进入区域的地址

4. Java堆(线程共享)

(1) 是什么?

    所有的对象实例以及数组都要在堆上分配。是垃圾收集器管理的主要区域。

(2) 分区

① 新生代: Eden区、Survivor From区、Survivor To区
② 老年代

5. 方法区(线程共享)

(1) 是什么

    方法区用于存储已被虚拟机加载的类信息、方法、常量、静态成员变量、JIT(即时编译器)编译后的代码等数据,在类加载时分配。

(2) 也叫非堆,分配在元空间

    元空间:类的元数据,如方法数据、方法信息(字节码,栈和变量大小)、运行时常量池、已确定的符号引用和虚方法表等方法区的数据,保存在本地内存区域(堆外内存)

6. 运行时常量池(线程共享)

(1) 是什么

    运行时常量池用于存放编译期和运行期生成的各种字面量和符号引用。这部分内容将在类加载后进入方法区的运行时常量池中存放。属于方法区的一部分

(2) 字面量和符号引用

    字面量:1.字符串;2.基本类型值;3.final常量     符号引用:1.类和方法的全限定名;2.字段的名称和描述符;3.方法的名称

二、 Jvm内存模型

1. 定义

    由于不同平台内存模型的差异,有可能导致程序在不同平台的并发访问出错。Java内存模型(Java Memory Model,JMM)是屏蔽各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的内存访问效果。

2. 具体操作

    定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量的底层细节。
    此处的变量是指实例字段,静态字段和构成数组对象的元素,不包括局部变量与方法参数

3. 主内存和工作内存

    Jvm内存模型规定所有的变量都存储在主内存中,每条线程还有自己的工作内存,工作内存保存了被该线程使用到的变量的主内存副本拷贝。

4. synchronization、final、volatile

(1) synchronization

① 互斥

    对于一个monitor对象,当被一个线程持有,其他线程只能等待

② 可见性

    保证了线程在同步代码块期间写入动作,对于后续进入该代码块的线程是可见的(持有相同monitor对象的线程)。
    当前线程释放monitor对象,作用是把cpu缓存数据刷新到主内存中;其他线程进入该代码块时,需要获取monitor对象,会使cpu缓存失效,从而使变量从主内存中重新加载。

③ 禁止指令重排序

(2) final

① 禁止指令重排序
② 可见性

    被final修饰的字段在构造器中一旦初始化完成,并且构造器没有把”this”引用传递出去(“this”引用逃逸是一件很危险的事情,其他线程有可能通过这个引用访问到”初始化了一半”的对象),那么其他线程就能看见final字段的值。

(3) volatile

① 可见性
② 禁止指令重排序

5. 示例

(1) 重排序

(2) 可见性

(3) 互斥性

作者:陶章好
链接:juejin.cn/post/684490… 来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。