文章目录

  • 1. JVM内存模型
    • 程序计数器:线程私有
    • Java虚拟机栈:线程私有
    • 本地方法栈:线程私有
    • 堆:线程共享
    • 方法区:线程共享
    • JDK1.7和1.8 内存模型的区别
  • 2. Java内存模型(JMM)
  • 3 . Java对象的创建过程

1. JVM内存模型

Java 虚拟机在执⾏ Java 程序的过程中会把它管理的内存划分成若⼲个不同的数据区域。JDK1.8 和之前的版本略有不同,下⾯会介绍到。

首先对于一个进程来说,它包含多个线程,每个线程都有其独立的内存区域,包括:虚拟机栈,本地方法栈和程序计数器。

程序计数器:线程私有

记录当前线程所执行到的字节码的行号。
每个线程都有一个独立的程序计数器,各线程之间计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存区域。
它是唯一没有OutOfMemoryError情况的内存区域。
它的⽣命周期随着线程的创建⽽创建,随着线程的结束⽽死亡。

程序计数器在哪些地方用到了?
字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复登基础功能都需要依赖这个计数器来完成。

Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器。

Java虚拟机栈:线程私有

描述的是 Java ⽅法执⾏的内存模型,每个Java方法在执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、⽅法出⼝等信息。

每个Java方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。

Java 虚拟机栈也是线程私有的,每个线程都有各⾃的Java虚拟机栈,⽽且随着线程的创建⽽创建,随着线程的死亡⽽死亡。

局部变量表
局部变量表主要存放了编译器可知的各种数据类型(boolean、byte、char、short、int、float、long、double)、对象引⽤(reference类型,它不同于对象本身,可能是⼀个指向对象起始地址的引⽤指针,也可能是指向⼀个代表对象的句柄或其他与此对象相关的位置)和returnAddress类型(指向了一条字节码指令的地址)。

这些数据类型在局部变量表中的存储空间是以局部变量槽来表示,其中64位长度的long和double类型的数据会占用两个变量槽,其余的数据类型只占用一个。

局部变量表所需的内存空间在编译期间完成分配。当进入一个方法时,这个方法需要在栈帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小。

Java 虚拟机栈会出现两种异常:StackOverFlowError 和 OutOfMemoryError。
StackOverFlowError:若Java虚拟机栈的内存⼤⼩不允许动态扩展,那么当线程请求栈的深度超过当前Java虚拟机栈的最⼤深度的时候,就抛出StackOverFlowError异常。(典型的场景有:递归调用和死循环)
OutOfMemoryError:若 Java 虚拟机栈的内存⼤⼩允许动态扩展,且当线程请求栈时内存⽤完了,⽆法再动态扩展了,此时抛出OutOfMemoryError异常。

在栈上分配对象
大多数对象都在堆上分配内存空间,但是由于即时编译技术的进步,尤其是逃逸分析技术的日渐强大,栈上分配,标量替换优化手段已经导致对象在堆上分配不是那么绝对了。

本地方法栈:线程私有

本地方法栈和虚拟机栈所发挥的作⽤⾮常相似,区别是: 虚拟机栈为虚拟机执⾏ Java ⽅法 (也就是字节码)服务,⽽本地⽅法栈则为虚拟机使⽤到的 Native ⽅法服务。 在 HotSpot 虚拟机中和 Java 虚拟机栈合⼆为⼀。本地⽅法被执⾏的时候,在本地⽅法栈也会创建⼀个栈帧,⽤于存放该本地⽅法的局部变量表、操作数栈、动态链接、出⼝信息。

⽅法执⾏完毕后相应的栈帧也会出栈并释放内存空间,也会出现 StackOverFlowError 和OutOfMemoryError 两种异常。

看完了线程私有的内存区域,在来看看线程共享的内存区域:

堆:线程共享

Java 虚拟机所管理的内存中最⼤的⼀块,Java 堆是所有线程共享的⼀块内存区域,在虚拟机启动时创建。

此内存区域的唯⼀⽬的就是存放对象实例,⼏乎所有的对象实例以及数组都在这⾥分配内存。

堆分区
Java 堆是垃圾收集器管理的主要区域,因此也被称作GC堆(Garbage Collected Heap)。

从垃圾回收的⻆度,由于现在收集器基本都采⽤分代垃圾收集算法,所以Java堆还可以细分为:新⽣代和⽼年代。
新生代再细致⼀点有:Eden空间、From Survivor、To Survivor空间等。
进⼀步划分的⽬的是更好地回收内存,或者更快地分配内存。

上图所示的 eden区、s0区、s1区都属于新⽣代,tentired 区属于⽼年代。⼤部分情况,对象都会⾸先在 Eden 区域分配,在⼀次新⽣代垃圾回收后,如果对象还存活,则会进⼊ s0 或者 s1,并且对象的年龄还会加 1(Eden区i>Survivor 区后对象的初始年龄变为1),当它的年龄增加到⼀定程度(默认为15岁),就会被晋升到⽼年代中。对象晋升到⽼年代的年龄阈值,可以通过参数 -XX:MaxTenuringThreshold 来设置。

方法区:线程共享

它⽤于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。

⽅法区也被称为永久代。很多⼈都会分不清⽅法区和永久代的关系,为此我也查阅了⽂献。永久代是对方法区的一种实现方式。方法区是一种定义,永久代是一种实现。

运⾏时常量池
运⾏时常量池是⽅法区的⼀部分。Class ⽂件中除了有类的版本、字段、⽅法、接⼝等描述信息外,还有常量池信息(⽤于存放编译期⽣成的各种字⾯量和符号引⽤)

既然运⾏时常量池时⽅法区的⼀部分,⾃然受到⽅法区内存的限制,当常量池⽆法再申请到内存时会抛出 OutOfMemoryError 异常。

JDK1.7及之后版本的 JVM 已经将运⾏时常量池从⽅法区中移了出来,在 Java 堆(Heap)中开辟了⼀块区域存放运⾏时常量池。字符串常量池1.7以后也是放在堆中

JDK1.7和1.8 内存模型的区别

JDK1.7JVM内存模型:
线程私有:Java虚拟机栈、本地方法栈、程序计数器
线程共享:方法区、堆

JDK1.8JVM内存模型:

JDK1.8与1.7最大的区别是1.8将永久代(方法区)取消,取而代之的是元空间。

JDK1.7方法区是由永久代实现的,JDK1.8方法区是由元空间实现的,元空间属于本地内存,所以元空间的大小受本地内存的限制。

直接内存
直接内存并不是虚拟机运⾏时数据区的⼀部分,也不是虚拟机规范中定义的内存区域,但是这部分内存也被频繁地使⽤。⽽且也可能导致 OutOfMemoryError 异常出现。

2. Java内存模型(JMM)

Java内存模型规定所有的变量都存储在主内存中,每条线程还有自己的工作内存,线程的工作内存中保存了被该线程使用到的变量的主内存副本的拷贝,线程对变量的所有操作(读取、赋值等)都必须在工作内存中进行,而不能直接读写主内存中的变量。不同的线程之间也无法访问对方工作内存中的变量,线程间变量值的传递均需要通过主内存来完成。

主内存:主要对应Java堆中的对象实例数据部分。(寄存器,高速缓存)
工作内存:对应于虚拟机栈中的部分区域。(硬件的内存)

3 . Java对象的创建过程

类加载检查: 虚拟机遇到⼀条 new 指令时,⾸先将去检查这个指令的类参数是否能在常量池中定位到这个类的符号引⽤,并且检查这个符号引⽤代表的类是否已被加载过、解析和初始化过。如果没有,那必须先执⾏相应的类加载过程。(详细的类加载机制会新出一篇博客)

分配内存: 在类加载检查通过后,接下来虚拟机将为新⽣对象分配内存。对象所需的内存⼤⼩在类加载完成后便可确定,为对象分配空间的任务等同于把⼀块确定⼤⼩的内存从 Java 堆中划分出来。分配⽅式有 “指针碰撞” 和 “空闲列表” 两种,选择那种分配⽅式由 Java 堆是否规整决定,⽽Java堆是否规整⼜由所采⽤的垃圾收集器是否带有压缩整理功能决定。

初始化零值:内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头),这⼀步操作保证了对象的实例字段在 Java 代码中可以不赋初始值就直接使⽤,程序能访问到这些字段的数据类型所对应的零值。

设置对象头: 初始化零值完成之后,虚拟机要对对象进⾏必要的设置,例如这个对象是那个类的实例、如何才能找到类的元数据信息、对象的哈希吗、对象的 GC 分代年龄等信息。 这些信息存放在对象头中。 另外,根据虚拟机当前运⾏状态的不同,如是否启⽤偏向锁等,对象头会有不同的设置⽅式。

执⾏ init ⽅法: 在上⾯⼯作都完成之后,从虚拟机的视⻆来看,⼀个新的对象已经产⽣了,但从Java 程序的视⻆来看,对象创建才刚开始, ⽅法还没有执⾏,所有的字段都还为零。所以⼀般来说,执⾏ new 指令之后会接着执⾏ ⽅法,把对象按照程序员的意愿进⾏初始化,这样⼀个真正可⽤的对象才算完全产⽣出来。

[注意]:执行方法,即对象按照程序员的意愿进行初始化。对应到语言层面上讲,就是为属性赋值(注意,这与上面的赋零值不同,这是由程序员赋的值),和执行构造方法。

JVM内存模型和java内存模型相关推荐

  1. jvm内存模型和java内存模型_JVM运行时内存模型综述

    JVM内存模型 JVM分为五个区域:虚拟机栈.本地方法栈.方法区.堆.程序计数器. JVM不同区域的占用内存大小不同,一般情况下堆最大,程序计数器较小. JVM五个区中虚拟机栈.本地方法栈.程序计数器 ...

  2. Java内存模型和Java内存结构精读

    以前看过很多遍JVM相关知识的文章,无非都是直接来张图片开搞,一来就甩张图片上来,这是方法区,这是堆,这是线程独享的一堆堆的概念,看得真的是头大,死记硬背也记不下来,更别说理解了. 最近一段时间在看j ...

  3. java 堆内存结构_JVM内存结构、Java内存模型和Java对象模型

    JVM内存结构 我们都知道,Java代码是要运行在虚拟机上的,而虚拟机在执行Java程序的过程中会把所管理的内存划分为若干个不同的数据区域,这些区域都有各自的用途.其中有些区域随着虚拟机进程的启动而存 ...

  4. 基于JVM原理、JMM模型和CPU缓存模型深入理解Java并发编程

    许多以Java多线程开发为主题的技术书籍,都会把对Java虚拟机和Java内存模型的讲解,作为讲授Java并发编程开发的主要内容,有的还深入到计算机系统的内存.CPU.缓存等予以说明.实际上,在实际的 ...

  5. 区分 JVM 内存结构、 Java 内存模型 以及 Java 对象模型 三个概念

    本文由 简悦 SimpRead 转码, 原文地址 https://www.toutiao.com/i6732361325244056072/ 作者:Hollis 来源:公众号Hollis Java 作 ...

  6. JVM内存结构 VS Java内存模型 VS Java对象模型

    Java作为一种面向对象的,跨平台语言,其对象.内存等一直是比较难的知识点.而且很多概念的名称看起来又那么相似,很多人会傻傻分不清楚.比如本文我们要讨论的JVM内存结构.Java内存模型和Java对象 ...

  7. 快速带你分清java内存结构,java内存模型,java对象模型和jvm内存结构!

    现如今你是否有这样的感觉,无论生活还是学习,节奏都是非常的快,每天面对海量的知识信息,自己感觉都要hold不住了,每天打开微信公众号,是不是发现有几十条未读,无论是技术文章还是其他类型的文章,我们大多 ...

  8. Java 内存模型和 JVM 内存结构真不是一回事

    这两个概念估计有不少人会混淆,它们都可以说是 JVM 规范的一部分,但真不是一回事!它们描述和解决的是不同问题,简单来说, Java 内存模型,描述的是多线程允许的行为 JVM 内存结构,描述的是线程 ...

  9. java内存 海子_Java虚拟机:JVM内存模型和volatile详解

    JVM内存模型和volatile详解 Java内存模型 随着计算机的CPU的飞速发展,CPU的运算能力已经远远超出了从主内存(运行内存)中读取的数据的能力,为了解决这个问题,CPU厂商设计出了CPU内 ...

  10. jvm面试2 jvm如何加载java代码? JVM知识重点:内存模型和GC

    jvm如何加载java代码? native方法forName0 JVM知识重点:内存模型和GC' 注意:jvm是一个内存中的虚拟机 下面是Class类中,我们常用的forName方法 @CallerS ...

最新文章

  1. Ant Design Pro 改变默认启动端口号
  2. 物料信息记录中几个常见的数据表
  3. OpenCASCADE:Foundation Classes之异常
  4. C#数“.NET研究”据本地存储方案之SQLite
  5. 基于SSD的自动路径规划算法
  6. 微软发布ML.NET 1.0,可一键添加机器学习模型
  7. mysql8.0与mysql7.0_MySQL 5.7 vs 8.0,哪个性能更牛?
  8. 垃圾回收算法与实现系列-锁在应用层的优化思路
  9. 程序员面试金典——2.3访问单个结点的删除
  10. linux误用rm删除文件后恢复
  11. 罗技G29方向盘Mac驱动
  12. 详解RS485电路,就是那么简单!
  13. 问卷调查:自定义表单设计vue
  14. I/O——Spring cache abstraction
  15. 幸福家庭杂志幸福家庭杂志社幸福家庭教育部2022年第1期目录
  16. 【机器学习】经典的机器学习200道面试题(附参考答案)
  17. Dubbo解析及原理浅析
  18. 测试人员必知的软件测试文档有哪些?
  19. 出No core dump will be written. Minidumps are not enabled by default on client versions of Windows
  20. 无人机亲当“马前卒”,京东对外赋能“剑指”智慧农业

热门文章

  1. 给pmbus添加mfr_id, mfr_version, mfr_model节点显示
  2. 软考资料合集/软考真题合集(软件设计师/网络工程师/系统分析师/系统架构师/软件测评师/程序员等)
  3. signature=c9b7b92b79e9a32ac6be9993bfe5df5a,这字幕= =太销魂了
  4. Java程序开发的基本流程是什么样的?
  5. [人体参考]_人体各部分布线图人体解剖参考资料下载!
  6. 员工申请加薪无望辞职,老板:不知感恩
  7. Java开发过程中遇到的问题及解决方法
  8. 抓取html文件swf,如何把网页上的flash动画保存为swf格式文件(缓存提取)
  9. C# 实现简易的串口监视上位机功能附源码下载
  10. 最好用的HDR图像处理器——Photomatix Pro新功能介绍及使用教程