Java 内存模型和 JVM 内存结构真不是一回事
这两个概念估计有不少人会混淆,它们都可以说是 JVM 规范的一部分,但真不是一回事!它们描述和解决的是不同问题,简单来说,
- Java 内存模型,描述的是多线程允许的行为
- JVM 内存结构,描述的是线程运行所设计的内存空间
JVM 是什么呢?它屏蔽了底层架构的差异性,是 Java 跨平台的依据,也是每个 Java 程序员必须了解的一部分。
JVM 体系结构
Java Virtual Machine(JVM) 是一种抽象的计算机,基于堆栈架构,它有自己的指令集和内存管理。它加载 class 文件,分析、解释并执行字节码。基本结构如下:
如上图所示,JVM 主要分为三个子系统:类加载器、运行时数据区和执行引擎。
类加载器子系统
它主要功能是处理类的动态加载,还有链接,并且在第一次引用类时进行初始化。
Loading - 加载,顾名思义,用于加载类,它有三种类加载器,根据双亲委托模型,从不同路径进行加载:
- Bootstrap ClassLoader - 加载 rt.jar 核心类库,是优先级最高的加载器
- Extension ClassLoader - 负责加载 jre\lib\ext 文件夹中的类
- Application ClassLoader -负责加载 CLASSPATH 指定的类库
Linking - 链接,动态链接到运行时所需的资源,分为三步:
- Verify - 验证:验证生成的字节码是否正确
- Prepare - 准备:为所有静态变量,分配内存并赋予默认值
- Resolve - 解析:将 class 文件常量池中所有对内存的符号引用,替换成到方法区的直接引用
Initialization - 类初始化,类加载的最后阶段,这里对静态变量进行赋值,并执行静态块。(注意区分对象初始化)
运行时数据区
它约定了在运行时程序代码的数据比如变量、参数等等的存储位置,主要包含以下几部分:
- PC 寄存器(程序计数器):保存正在执行的字节码指令的地址
- 栈:在方法调用时,创建一个叫栈帧的数据结构,用于存储局部变量和部分过程的结果,栈帧由以下几部分组成:
- 局部变量表:存储方法调用时传递的参数,从0开始存储this、方法参数、局部变量
- 操作数栈:执行中间操作,存储从局部变量表或对象实例字段复制的常量或变量值,以及操作结果,另外,还用来准备被调用方法的参数和接受方法调用的返回结果
- 动态链接:一个指向运行时常量池的引用,将 class 文件中的符号引用(描述一个方法调用了其他方法或访问成员变量)转为直接引用
- 方法返回地址:方法正常退出或抛出异常退出,返回方法被调用的位置
- 堆:存储类实例对象和数组对象,垃圾回收的主要区域
- 方法区:也被称为元空间,还有个别名 non-heap(非堆),使用本地内存存储 class meta-data 元数据(运行时常量池,字段和方法的数据,构造函数和方法的字节码等),在 JDK 8 中,把 interned String 和类静态变量移动到了 Java 堆
- 运行时常量池:存储类或接口中的数值字面量,字符串字面量以及所有方法或字段的引用,基本上涉及到方法或字段,JVM 就会在运行时常量池中搜索其具体的内存地址
- 本地方法栈:与 JVM 栈类似,只不过服务于 Native 方法
执行引擎
运行时数据区存储着要执行的字节码,执行引擎将会读取并逐个执行。
Interpreter - 解释器,它对字节码的解释很快,但执行慢,有个缺点是,当方法被多次调用时,每次都需要重新解释。
JIT Compiler- JIT编译器, 解决了解释器的缺点,仍使用解释器来转换字节代码,但发现有代码重复执行时,会使用 JIT 编译器,将整个字节码编译成本地代码,将本地代码用于重复调用,从而提高系统的性能,有以下几部分组成:
- 中间代码生成器 - 生成中间代码
- 代码优化器 - 负责优化上面生成的中间代码
- 目标代码生成器 - 负责生成机器代码或本地代码
- Profiler - 一个特殊组件,负责查找热点,判断该方法是否被多次调用
Garbage Collector- 垃圾收集器,收集和删除未引用的对象。
另外,还包括执行引擎所需的本地库(Native Method Libraries)和与其交互的 JNI 接口(Java Native Interface)。
现在来看下 Java 内存模型和 JVM 内存结构有何不同。
JVM 内存结构
常说的 JVM 内存结构指的就是上文提交到运行时数据区,其中堆、方法区被线程共享,程序计数器、栈、运行时常量池被线程独享。
它描述的是,在运行时,字节码和代码数据存储的位置。
内存模型
先抛开 Java 不说,先来看下内存模型是什么?维基百科中的定义:
In computing, a memory model describes the interactions of threads through memory and their shared use of the data.
意思就是,在计算中,内存模型描述了多线程如何正确的通过内存进行交互和使用共享数据。换句话说,内存模型约束了处理器对内存的读写。
CPU 和内存之间通常会存在一层或多层高速缓存,这对单处理器可能没问题,但在多处理器系统中,可能就会出现缓存一致性问题,也就是当两个处理器(线程)同时读取相同内存位置会发生什么?什么情况下会看到相同的值?
缓存一致性问题,在并发编程中,又被称作可见性问题。内存模型在处理器级别,为处理器彼此之间对内存写入结果的可见性,定义了充分必要条件:
- 强内存模型,一般说的是顺序一致性,所有内存操作存在一个全序关系,每个操作都是原子的且立即对所有处理器可见
- 弱内存模型,不限制处理器的内存操作顺序,而使用特殊指令刷新或者使本地缓存失效,以便看到其他处理器的写入,或使此处理器的写入对其他处理器可见,这些特殊指令被称为内存屏障
大多数处理器不会限制内存操作的顺序,多线程在执行时可能会出现让人困惑和违背直觉的结果。这是因为 CPU 为了充分利用不同类型存储器(寄存器、高速缓存、主存)的总线带宽,会将内存操作重新排序,以无序执行,这个动作称为内存排序或指令重排序。
重排序,也被称为编译器优化和处理器优化,因为它既可以发生在编译期间,也可以发生在 CPU 运行时。为了保证多线程的有序性,需要使用内存屏障禁止重排序。
所以说,内存模型就是在硬件层面描述了使用内存屏障(刷新缓存或禁用指令重排序)解决多线程编程中的可见性和有序性的问题。
Java 内存模型
Java 内存模型(下文简称 JMM)就是在底层处理器内存模型的基础上,定义自己的多线程语义。它明确指定了一组排序规则,来保证线程间的可见性。
这一组规则被称为 Happens-Before, JMM 规定,要想保证 B 操作能够看到 A 操作的结果(无论它们是否在同一个线程),那么 A 和 B 之间必须满足 Happens-Before 关系:
- 单线程规则:一个线程中的每个动作都 happens-before 该线程中后续的每个动作
- 监视器锁定规则:监听器的解锁动作 happens-before 后续对这个监听器的锁定动作
- volatile 变量规则:对 volatile 字段的写入动作 happens-before 后续对这个字段的每个读取动作
- 线程 start 规则:线程 start() 方法的执行 happens-before 一个启动线程内的任意动作
- 线程 join 规则:一个线程内的所有动作 happens-before 任意其他线程在该线程 join() 成功返回之前
- 传递性:如果 A happens-before B, 且 B happens-before C, 那么 A happens-before C
Java 提供了几种语言结构,包括 volatile, final 和 synchronized, 它们旨在帮助程序员向编译器描述程序的并发要求,其中:
- volatile - 保证可见性和有序性
- synchronized - 保证可见性和有序性; 通过管程(Monitor)保证一组动作的原子性
- final - 通过禁止在构造函数初始化和给 final 字段赋值这两个动作的重排序,保证可见性(如果 this 引用逃逸就不好说可见性了)
编译器在遇到这些关键字时,会插入相应的内存屏障,保证语义的正确性。
所以说,Java 内存模型描述的是多线程对共享内存修改后彼此之间的可见性,另外,还确保正确同步的 Java 代码可以在不同体系结构的处理器上正确运行。
小结
它们之间的关系可以这样来个总结,实现一个 JVM 要满足内存结构描述的组成部分,设计如何执行多个线程的时候,要满足Java 内存模型约定的多线程语义。
Java 内存模型和 JVM 内存结构真不是一回事的更多相关文章
- 【Java】JMM内存模型和JVM内存结构
JMM内存模型和JVM内存结构 JAVA内存模型(Java Memory Model) Java内存模型,一般指的是JDK 5 开始使用的新的内存模型,主要由JSR-133: JavaTM Memor ...
- Java内存模型和JVM内存管理
Java内存模型和JVM内存管理 一.Java内存模型: 1.主内存和工作内存(即是本地内存): Java内存模型的主要目标是定义程序中各个变量的访问规则,即在JVM中将变量存储到内存和从内存中取 ...
- JVM内存结构、Java内存模型和Java对象模型
Java作为一种面向对象的,跨平台语言,其对象.内存等一直是比较难的知识点.而且很多概念的名称看起来又那么相似,很多人会傻傻分不清楚.比如本文要讨论的JVM内存结构.Java内存模型和Java对象模型 ...
- 并发一:Java内存模型和Volatile
并发一:Java内存模型和Volatile 一.Java内存模型(JMM) Java内存模型的主要目标是定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和在内存中取出变量的底层细节,是围绕着 ...
- JAVA内存模型和Happens-Before规则
前言 上一篇文章王子给大家介绍了并发编程中比较关心的三个核心问题,可见性.有序性和原子性. 今天我们继续来探索并发编程的内容,聊一聊JAVA的内存模型和Happens-Before规则. JAVA内存 ...
- 黑马-----内存模型和volatile详解
黑马程序员:Java培训.Android培训.iOS培训..Net培训 JAVA线程-内存模型和volatile详解 一.单核内存模型 1.程序运行时,将临时数据存放到Cache中 2.将CPU计算所 ...
- Java SE之调整JVM内存笔记
[文档整理系列] Java SE之调整JVM内存笔记 一般JVM内存限制是64Mbyte Eclipse下 Run as configrationArguments选项:-Xmx80m [设置虚拟机 ...
- Java虚拟机详解----JVM内存结构
http://www.cnblogs.com/smyhvae/p/4748392.htm 主要内容如下: JVM启动流程 JVM基本结构 内存模型 编译和解释运行的概念 一.JVM启动流程: JVM启 ...
- JAVA内存模型与JVM内存结构
问题:什么事java内存模型? 首先呢不要答堆.栈.方法区.这是JVM的内存结构.下面阐述了JMM和JVM的区别和自己对JMM的见解 1.Java内存模型(JMM):即多线程相关的.定义了一个线程对另 ...
随机推荐
- 【EdgeBoard体验】开箱与上手
简介 市面上基于嵌入式平台的神经网络加速平台有很多,今天给大家带来是百度大脑出品的EdgeBoard.按照官网文档的介绍,EdgeBoard是基于Xilinx Zynq Ultrascale+ MPS ...
- Web前端三大框架_vue源码笔记
一.VUE 1.1 MVVM VUE也是基于MVVM模式实现的.特点就是数据双向绑定 在MVVM模式中,分成三个部分: M 模型 model V 视图 view VM 视图-模型 view-model ...
- ElasticSearch01--安装ElasticSearch服务(Linux)
在linux系统上安装ElasticSearch服务 Linux系统要求: 1.centos6或centos7 2.jdk1.8及以上 1. 新建用户 新建一个用户 useradd yuank 修改用 ...
- 「PowerBI」分析服务多维数据结构重回关系数据库的一大绝招
在过往Excel催化剂定位的轻量级Excel+PowerBIDesktop的解决方案中,已经做过了近乎完美的PowerBIDesktop数据模型数据导出到Excel工作表的应用,这也是个人版数据应用的 ...
- 6.2.初识Flutter应用之路由管理
路由管理 路由(Route)在移动开发中通常指页面(Page),这跟web开发中单页应用的Route概念意义是相同的,Route在Android中通常指一个Activity,在iOS中指一个ViewC ...
- java练习---9
//程序员:罗元昊 2017.10.22 package cn.lyh; import com.rupeng.game.GameCore; public class L implements Runn ...
- Java NIO ByteBuffer 的使用与源码研究
一.结论 ByteBuffer 是Java NIO体系中的基础类,所有与Channel进行数据交互操作的都是以ByteBuffer作为数据的载体(即缓冲区).ByteBuffer的底层是byte数组, ...
- cookbook_类与对象
1修改实例的字符串表示 可以通过定义__str__()和__repr__()方法来实现 class Pair: def __init__(self,x,y): self.x = x self.y = ...
- Linux文件系统损坏导致无法正常启动与fsck修复工具
今天在打开自己的虚拟机学习的时候,发现在文件系统检查过程中出现以下的报错: /dev/mapper/VolGroup-lv_root:UNEXPECTED INCONSISTENCY;RUN fsck ...
- vuex的实现
源代码可以查看我的github: https://github.com/Jasonwang911/TryHardEveryDay/tree/master/Vuex/vuex-resouce 欢迎s ...