0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Java运行时内存区域与硬件内存的关系1

jf_78858299 来源:小牛呼噜噜 作者:小牛呼噜噜 2023-02-09 14:41 次阅读

什么是 JMM?

在上一篇文章中,我们了解了计算机由于各个硬件的读取速度之间的巨大差距,和充分利用CPU的性能的手段方法,及其所带来的一系列问题:

  1. 为了充分压榨CPU的性能, CPU 会对指令乱序执行或者语言的编译器会指令重排 ,让CPU一直工作不停歇,但同时会导致有序性问题
  2. 为了平衡CPU的寄存器和内存的速度差异,计算机的CPU 增加了高速缓存,但同时导致了 可见性问题
  3. 为了平衡CPU 与 I/O 设备的速度差异,操作系统增加了进程、线程概念,以分时复用 CPU,但同时导致了原子性问题

Java 是最早尝试提供内存模型的编程语言。由于Java 语言是跨平台的,另外各个操作系统总存在一些差异,Java在物理机器的基础上抽象出一个内存模型(JMM)

JMM 可以看作是 Java 定义的并发编程相关的一组规范,除了抽象了线程和主内存之间的关系之外,其还规定了从 Java 源代码到 CPU 可执行指令的这个转化过程要遵守哪些和并发相关的原则和规范,这样就可以屏蔽各个操作系统的差异,简化多线程编程。

Java 运行时内存区域与硬件内存的关系

Java 内存区域和Java内存模型有何区别?

这是一个非常容易让人混淆的问题,Java 内存区域和内存模型完全是不一样的东西,

  1. Java 内存区域, 也叫内存区域JVM内存模型,和 Java 虚拟机(JVM)的运行时区域相关,是指 JVM运行时将数据分区域存储,强调对内存空间的划分。
  2. Java内存模型,也叫内存模型(JMM),是Java 定义的并发编程相关的一组规范,除了抽象了线程和主内存之间的关系之外,其还规定了从 Java 源代码到 CPU 可执行指令的这个转化过程要遵守哪些和并发相关的原则和规范,屏蔽各个操作系统的差异。通俗点说: JMM规范了程序中变量的访问规则,保证了操作的原子性、可见性、有序性, 我们下文慢慢道来。

我们知道JVM 运行时内存区域是分区域的,分为栈、堆等,其实这些都是 JVM 定义的逻辑概念。但在传统的硬件内存架构中是没有栈和堆这种概念。

其中:

  1. 图中栈可以细分为:虚拟机栈(JVM Stacks) 本地方法栈(Native Method Stack)
  • 虚拟机栈(JVM Stacks): 线程私有,它的生命周期和线程相同 ,描述的是Java方法执行的内存模型,每个方法在执行的同时都会创建一个线帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息,每个方法从调用直至执行完成的过程,都对应着一个线帧在虚拟机栈中入栈到出栈的过程
  • 本地方法栈(Native Method Stack): 线程私有 ,本地方法栈与虚拟机栈的作用是一样的,只不过虚拟机栈是服务Java方法的,而本地方法栈是为虚拟机调用Native方法服务的。在Java虚拟机规范中对于本地方法栈没有特殊的要求,虚拟机可以自由的实现它,因此 在Sun HotSpot虚拟机直接把本地方法栈和虚拟机栈合二为一了 。线程开始调用本地方法时,会进入 不再受 JVM 约束的世界。本地方法可以通过 JNI(Java Native Interface)来访问虚拟机运行时的数据区,甚至可以调用寄存器,具有和 JVM 相同的能力和权限。JNI 类本地方法最著名的应该是 System.currentTimeMillis()
  1. 堆(Heap)

虚拟机堆是Java虚拟机中内存最大的一块,是被所有线程共享的,在虚拟机启动时候创建,Java堆唯一的目的就是存放对象实例,几乎所有的对象实例都在这里分配内存,随着JIT编译器的发展和逃逸分析技术的逐渐成熟,栈上分配、标量替换优化的技术将会导致一些微妙的变化,所有的对象都分配在堆上渐渐变得不那么“绝对”了。

Java中栈和堆既存在于计算机的高速缓存中,又存在于主存中,所以两者并没有很直接的关系。

Java 线程与主内存的关系

Java 内存模型(JMM) 抽象了线程和主内存之间的关系,就比如说线程之间的共享变量必须存储在主内存中。在 JDK1.2 之前,Java 的内存模型实现总是从 主存 (即共享内存)读取变量,是不需要进行特别的注意的。而在当前的 Java 内存模型下,线程可以把变量保存 本地内存 (比如机器的寄存器)中,而不是直接在主存中进行读写。这就可能造成一个线程在主存中修改了一个变量的值,而另外一个线程还继续使用它在寄存器中的变量值的拷贝,造成数据的不一致。

什么是主内存?什么是本地内存?

  • 主内存 :所有线程创建的实例对象都存放在主内存中,不管该实例对象是成员变量还是方法中的本地变量(也称局部变量)
  • 本地内存 :每个线程都有一个私有的本地内存来存储共享变量的副本,并且,每个线程只能访问自己的本地内存,无法访问其他线程的本地内存。本地内存是 JMM 抽象出来的一个概念,存储了主内存中的共享变量副本。

Java 内存模型其实是一种规范,定义了很多东西:

  • 所有的变量都存储在主内存(Main Memory)中。
  • 每个线程都有一个私有的本地内存 (Local Memory),本地内存中存储了该线程以读/写共享变量的拷贝副本。
  • 线程对变量的所有操作都必须在本地内存中进行,而不能直接读写主内存。
  • 不同的线程之间无法直接访问对方本地内存中的变量。

这里所讲的主内存、工作内存与 Java 内存区域中的 Java 堆、栈、方法区等并不是同一个层次的内存划分,这两者基本上是没有关系的,如果两者一定要勉强对应起来,那从变量、主内存、工作内存的定义来看,主内存主要对应于Java堆中的对象实例数据部分,而工作内存则对应于虚拟机栈中的部分区域。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • JAVA
    +关注

    关注

    19

    文章

    2959

    浏览量

    104555
  • 编译器
    +关注

    关注

    1

    文章

    1618

    浏览量

    49054
  • JVM
    JVM
    +关注

    关注

    0

    文章

    157

    浏览量

    12209
收藏 人收藏

    评论

    相关推荐

    Labview 运行时内存增加

    的dll,用库函数直接调用这个dll后,Labview运行时所占的内存基本上保持在0.9 M左右,不会卡死了。附件里是那个网友上传的dll,大家可以下载后将.jpg改为.dll
    发表于 05-19 14:38

    C6748内存分配运行时出错

    因为需要对大量数据进行处理,我设置一个指针,内存分配1000*sizeof(float),运行时出错,查看其地址为0x00000000(肯定不对),如果减小分配空间,如200*sizeof
    发表于 03-16 10:05

    C语言内存运行时不同变量是怎样分配的

    C语言内存运行时不同变量是怎样分配的?怎样验证C语言编译后的内存地址分配是否合理?
    发表于 02-25 06:37

    请问单片机运行时内存是如何分配的?

    请问单片机运行时内存是如何分配的? 是在链接脚本中人工定义?还是编译器根据某种算法自动分配?
    发表于 09-27 08:16

    java线程内存模型

    一、Java内存模型 按照官方的说法:Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的
    发表于 09-27 10:55 0次下载
    <b class='flag-5'>java</b>线程<b class='flag-5'>内存</b>模型

    Java内存模型及原理分析

    一、Java内存模型 按照官方的说法:Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的
    发表于 09-28 11:49 0次下载
    <b class='flag-5'>Java</b><b class='flag-5'>内存</b>模型及原理分析

    利用StopWatch监控Java代码运行时间和分析性能

    利用StopWatch监控Java代码运行时间和分析性能。
    的头像 发表于 07-21 16:51 2785次阅读

    Java运行时内存区域硬件内存关系2

    在上一篇文章中,我们了解了计算机由于各个硬件的读取速度之间的巨大差距,和充分利用CPU的性能的手段方法,及其所带来的一系列问题: 1. 为了充分压榨CPU的性能, **CPU 会对指令乱序执行或者语言的编译器会指令重排** ,让CPU一直工作不停歇,但同时会导致`有
    的头像 发表于 02-09 14:41 302次阅读
    <b class='flag-5'>Java</b><b class='flag-5'>运行时</b><b class='flag-5'>内存</b><b class='flag-5'>区域</b>与<b class='flag-5'>硬件</b><b class='flag-5'>内存</b>的<b class='flag-5'>关系</b>2

    JVM运行时数据区之堆内存

    说一下 JVM 运行时数据区吧,都有哪些区?分别是干什么的?
    的头像 发表于 08-19 14:35 659次阅读
    JVM<b class='flag-5'>运行时</b>数据区之堆<b class='flag-5'>内存</b>

    如何查看java程序的内存分布

    要查看Java程序的内存分布,首先需要了解Java程序运行时内存模型。 Java程序的
    的头像 发表于 11-23 14:47 1001次阅读

    jvm内存模型和内存结构

    内存模型是指Java程序在运行时,JVM对内存空间的组织和管理方式。它包括了线程私有的部分和线程共享的部分。 线程私有部分 线程私有部分主要包含了栈(Stack)和程序计数器(Prog
    的头像 发表于 12-05 11:08 897次阅读

    jvm运行时内存区域划分

    内存区域划分对于了解Java程序的内存使用非常重要,本文将详细介绍JVM运行时内存
    的头像 发表于 12-05 14:08 508次阅读

    jvm管理的内存包括哪几个运行时数据内存

    JVM(Java虚拟机)是Java程序的运行环境,它提供了内存管理机制来管理Java程序所需的运行时
    的头像 发表于 12-05 14:09 529次阅读

    jvm内存区域中,哪一块是属于线程共享

    是如何划分的。JVM内存区域主要分为以下几个部分:程序计数器、Java虚拟机栈、本地方法栈、堆、方法区和运行时常量池。其中,程序计数器、Java
    的头像 发表于 12-05 14:14 1326次阅读

    java虚拟机内存包括远空间内存

    Java虚拟机(JVM)内存Java程序执行时所使用的内存空间的总称,包括了Java堆、方法区
    的头像 发表于 12-05 14:15 380次阅读