1 JVM的内存区域布局

  • java代码的执行步骤有三点

    • java源码文件->编译器->字节码文件
    • 字节码文件->JVM->机器码
    • 机器码->系统CPU执行
  • JVM执行的字节码需要用类加载来载入;字节码文件可以来自本地文件,可以在网络上获取,也可以实时生成。就是说你可以跳过写java代码阶段,直接生成字节码交由JVM执行
  • 其中Java虚拟机栈、程序计数器、Heap、本地方法栈、Metaspace属于JVM运行时的内存;按是否线程共享则可以分两类

  • JAVA堆和MetasSpace元空间属于线程共享的;虚拟机栈和本地方法栈、程序计数器是线程私有的

2 JVM五大数据区域介绍

  • 2.1 程序计数器(Progarm Counter Register)

    • 一块较小的内存空间, 是当前线程所执行的字节码的行号指示器。线程有一个独属的程序计数器,字节码解析工作时需要程序计数器来选取下一指令,分支、循环、跳转等依赖它
    • 正在执行java方法线程的计数器记录的是虚拟机字节码指令的地址;如果还是Native方法,则为空
    • 程序计数器内存区域是唯一一个在虚拟机中没有规定任何OutOfMemoryError错误的区域
  • 2.2 虚拟机栈(Virtual Machine Stack)

    • Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息
    • 每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程
    • 栈帧是用来存储数据和部分过程结果的数据结构,同时也被用来处理动态链接(Dynamic Linking)、 方法返回值和异常分派(Dispatch Exception)。栈帧随着方法调用而创建,随着方法结束而销毁(无论方法是正常完成还是异常完成)
    • 如果线程请求的栈深度大于虚拟机允许深度,则抛出StackOverflowError;扩展时无法申请到足够内存,则抛出OutOfMemeryError
  • 2.3 本地方法栈(Native Method Stack)
    • 本地方法栈和虚拟机栈作用类似,区别是虚拟机栈为执行Java方法服务,而本地方法栈则为Native方法服务。(HopShot的实现 直接把本地方法栈和虚拟机栈合二为一)
  • 上述3类区域,生命周期与Thread相同,即:线程创建时,相应的内存区创建,线程销毁时,释放相应内存
  • 2.4 堆(Heap)
    • 线程共享的一块内存区域,几乎所有的对象实例在这里分配内存,也是垃圾收集器进行垃圾收集的最重要的内存区域。因此很多时候也叫GC堆
    • 线程私有的分配缓存区(Thread Local Alloaction Buffer)也是在堆划分出来的
    • JDK8的版本,因使用元空间代替永久代,字符串常量池和类的静态变量也放入java堆中

  • 2.5 元空间(MetaSpace)
    • 主要存储类的元数据,比如类的各种描述信息,类名、方法、字段、访问限制等,既编译器编译后的代码等数据
    • 运行时常量池:Class文件中除了有类的版本、字段、方法等描述等信息外;还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分将在类加载后存放到元空间的运行时常量池中
  • 使用元空间代替永久代原因
    • 永久代的大小是在启动时固定好的,很难进行调优;太大则容易导致永久代溢出;太小在运行时,容易抛出OutOfMemeryError
    • 字符串存在永久代中,使用时易出问题,由于永久代内存经常不够用,爆出异常OutOfMemoryError: PermGen
  • CodeCache
    • JVM生成的native code存放的内存空间称之为Code Cache;JIT编译、JNI等都会编译代码到native code,其中JIT生成的native code占用了Code Cache的绝大部分空间
  • 直接内存
    • 它并不是虚拟机运行时数据区的一般分,也不在规范定义。JDK1.4,引入了Channel(通道)与Buffer(缓存区)的I/O方式,它可以使用Native函数分配堆外内存,可通过DirectByteBuffer操作。

3 JVM运行时内存布局和JMM内存模型区别

  • JVM内存区域是指JVM运行时将内存数据分区域存储,强调对内存空间的划分
  • JAVA内存模型是Java语言在多线程并发情况下对于共享变量内存操作的规范:解决变量在多线程的可见性、原子性的问题

4 JMM内存模型交互操作

  • 内存交互操作有八种,虚拟机的实现保证每一个操作都是原子性的

    • lock(锁定):作用于主内存的变量,标识变量为线程独占状态
    • unlock(解锁):作用于主内存的变量,释放一个处于锁定状态的变量,释放后的变量才可以被其他线程锁定
    • read(读取):作用于主内存变量,从主内存中读取出后面load操作要用到的变量
    • load(载入):作用于主内存中的变量,把刚才read的值放入工作内存的副本中
    • use(使用):作用于工作内存中的变量,当线程执行某个字节码指令需要用到相应的变量时,把工作内存中的变量副本传给执行引擎
    • assign(赋值):作用于工作内存中的变量,把一个从执行引擎中接受到的值放入工作内存的变量副本中
    • store(存储):作用于工作内存中的变量,把工作内存中的变量送到主内存,给后续的write使用
    • write(写入):作用于主内存中的变量,把store的工作内存中的变量值,写入主内存中
  • read和load 好像是相同的操作?各位有何高见,请指教下
  • JMM对这八种指令的使用,制定了如下规则
    • read和load、store和write必须顺序执行,而且两个指令绑定出现;就是说出现read就要有load
    • 不允许一个线程丢弃最近的assign操作,工作内存中的变量改变后,必须write同步到主内存
    • 不允许一个线程把没有发生assign操作的变量同步到主内存
    • 新的变量必须诞生于主内存,不允许工作内存使用一个没有初始化的变量;use、store操作变量之前,必须经过load和assign操作
    • 变量同一时刻只允许一个线程对其lock,该线程可以对该变量加锁多次,释放锁需要执行相同次数的unlock,lock和unlock要成对出现
    • 一个变量没有lock,不能unlock;并且一个线程不能unlock被其他线程锁住的变量
    • 执行unlock前,必须把工作内存中的变量同步到主内存中
    • 执行lock操作,需要清空工作内存(所有),并且需要使用该变量之前,要重新执行load和assign操作

欢迎指正文中错误

关注公众号,一起交流

参考文章

基础篇:JVM运行时内存布局的更多相关文章

  1. JVM运行时内存结构

    原文转载自:http://my.oschina.net/sunchp/blog/369707 1.JVM内存模型 JVM运行时内存=共享内存区+线程内存区 1).共享内存区 共享内存区=持久带+堆 持 ...

  2. JVM运行时内存组成分为一些线程私

    JVM运行时内存组成分为一些线程私有的,其他的是线程共享的. 线程私有 程序计数器:当前线程所执行的字节码的行号指示器. Java虚拟机栈:java方法执行的内存模型,每个方法被执行时都会创建一个栈帧 ...

  3. [转]JVM运行时内存结构

    [转]http://www.cnblogs.com/dolphin0520/p/3783345.html 目录[-] 1.为什么会有年轻代 2.年轻代中的GC 3.一个对象的这一辈子 4.有关年轻代的 ...

  4. Jvm运行时内存解析

    一.jvm的概念 在了解jvm的概念之前,我们先来了解java平台的逻辑结构,图片来自<深入java虚拟机> 从图中我们可以看到jdk包含了jre,java语言和java开发工具和Api, ...

  5. JVM 运行时内存结构

      1.JVM内存模型       JVM运行时内存=共享内存区+线程内存区 1).共享内存区       共享内存区=持久带+堆       持久带=方法区+其他       堆=Old Space ...

  6. JVM02——JVM运行时内存

    在上一篇文章中,我们介绍了 JVM 的内存区域,本文我们将继续围绕 JVM 展开话题,介绍 JVM 运行时内存.关注我的公众号「Java面典」了解更多 Java 相关知识点. Java 堆从 GC 的 ...

  7. 详细了解JVM运行时内存

    详细了解JVM运行时内存 1.程序计数器 概念 程序计数器也叫作PC寄存器,是一块很小的内存区域,可以看做是当前线程执行的字节码的行号指示器.字节码的解释工作就是通过改变程序计数器里面的值来获得下一条 ...

  8. Java Core - JVM运行时内存管理

    在读正文之前,阅读以下两篇博客学习并理解堆栈.作用域.本地方法的概念. 作用域:https://www.cnblogs.com/AlanLee/p/6627949.html 操作数栈:https:// ...

  9. 关于Class对象、类加载机制、虚拟机运行时内存布局的全面解析和推测

    简介: 本文是对Java的类加载机制,Class对象,反射原理等相关概念的理解.验证和Java虚拟机中内存布局的一些推测.本文重点讲述了如何理解Class对象以及Class对象的作用. 欢迎探讨,如有 ...

随机推荐

  1. Java多线程_生产者消费者模式1

    生产者消费者模型       具体来讲,就是在一个系统中,存在生产者和消费者两种角色,他们通过内存缓冲区进行通信,生产者生产消费者需要的资料,消费者把资料做成产品.生产消费者模式如下图.(图片来自网络 ...

  2. 求X值问题

    这,其实是一道数学题,难就难在要把数学模型用编程语言实现,其中的规律如果看不出来就比较鸡肋,这类题可以算是智商题,做这类题千万不能紧张,血的教训. 题目描述 已知有整数x,x + 100为一个平方数. ...

  3. 5G边缘计算:开源架起5G MEC生态发展新通路

    摘要:‍‍本文尝试从‍‍边缘计算的角度来阐述了‍‍为什么‍‍要把边缘计算当做一种新的生产关系来构建,‍‍以及如何用开源来构建这种新的生产关系. 5G推动新一轮工业革命 过去‍‍人类经历了三次工业革命, ...

  4. OpenCV(Open Source Computer Vision Library)计算机视觉库

    OpenCV(最基本的滤波到高级的物体检测皆有涵盖) 简介: OpenCV 是跨平台的,可以在  Windows.Linux.Mac OS.Android.iOS 等操作系统上运行. OpenCV 的 ...

  5. java安全编码指南之:Mutability可变性

    目录 简介 可变对象和不可变对象 创建mutable对象的拷贝 为mutable类创建copy方法 不要相信equals 不要直接暴露可修改的属性 public static fields应该被置位f ...

  6. laravel5Eloquent模型与数据表的创建

    下面是有关管理员模型与表的创建 生成模型时同时生成数据库迁移文件 在生成的迁移文件中添加字段 运行命令行生成数据表 命令进行混合运用 生成工厂文件,数据填充文件 工厂模型代码 数据填充文件代码 数据填 ...

  7. 深入了解Kafka【一】概述与基础架构

    1.概述 Kafka是一个分布式的.基于发布订阅的消息系统,主要解决应用解耦.异步消息.流量削峰等问题. 2.发布订阅模型 消息生产者将消息发布到Topic中,同时有多个消息消费者订阅该消息,消费者消 ...

  8. 12 props 传的是数组处理

    <template> <div>InfoDetailed</div> </template> <script> export default ...

  9. vue中实现后台管理路由标签页

    <template> <section> <div class="navTabList el-tabs__nav-scroll" id="t ...

  10. basicInterpreter1.02 增加对for循环的支持

    源码下载:https://files.cnblogs.com/files/heyang78/basicInterpreter102-20200531-2.rar 输入: for x= to print ...