JVM内存模型

简介: JVM内存模型

一:什么是JVM

JVM又称为虚拟机,是一种抽象化的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java虚拟机有自己完善的硬体架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。Java虚拟机屏蔽了与具体操作系统平台相关的信息,使得Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。   ------------来自 百度百科

二:JVM的内存结构

内存结构是JVM中比较重要的存储结构,是硬盘和cpu之间的桥梁,JVM的内存结构规定了程序在运行过程中的内存的申请,分配,管理等一系列策略,保证了程序的高效有序地进行。因为本人的JDK为1.8版本,因此我去百度了一下Java8的内存结构图,如下:

在Java8的内存结构图中,我们可以看出JVM内存主要由 堆,栈,程序计数器,方法区(元空间)等基本结构构成!下面,我们将详细看一下各部分的结构组成吧。

2.1Java堆(Java Heap)

Heap 堆:是JVM内存中最大的一块区域,由所有线程共享其资源,且是虚拟机中垃圾回收器主要管理的区域,由于堆中的资源是线程共享的,所以要考虑线程安全的问题。

在堆内存中主要放置以下资源:

1.实例对象:类初始化生成的对象,一般是由 new 关键字创建的对象,都放在堆内存中

2.线程分配缓冲区:线程私有但不影响堆的共性,可以提升对象分配的效率

3.字符串常量池:在Java1.7之前,字符串常量池是放在方法区(元空间)之中的,1.7之后为了提升字符串创建时的效率,将字符串常量池放在了堆内存中去了。

4.静态变量:由 static 关键字修饰这也与字符串常量池一样,在1.7之前也是放在方法区(元空间)之中的,在1.8之后也是放在了堆内存之中。

内存溢出:new 出对象,循环添加字符数据,当堆中没有内存空间可分配给实例,也无法再扩展时,就会抛出 OutOfMemoryError 异常

补充:

在 Java7 中堆内会存在年轻代、老年代和方法区(永久代)

1.Young 区被划分为三部分,Eden 区和两个大小严格相同的 Survivor 区。Survivor 区某一时刻只有其中一个是被使用的,另外一个留做垃圾回收时复制对象。在 Eden 区变满的时候,GC 就会将存活的对象移到空闲的 Survivor 区间中,根据 JVM 的策略,在经过几次垃圾回收后,仍然存活于 Survivor 的对象将被移动到 Tenured 区间

2.Tenured 区主要保存生命周期长的对象,一般是一些老的对象,当一些对象在 Young 复制转移一定的次数以后,对象就会被转移到 Tenured 区

3.Perm 代主要保存 Class、ClassLoader、静态变量、常量、编译后的代码,在 Java7 中堆内方法区会受到 GC 的管理

我在刷牛客题目编程的时候,也会刷到一些有关JVM堆内存的问题,例如:

-Xms:代表什么,-Xmx:代表什么,-Xmn又代表什么。这些我们还要深入了解学习哦!

(-Xms1024m:代表最小堆;-Xmx1024m:代表最大堆;-Xmn512m:代表新生代)

2.2 Java栈(Java Stacks)

Java 虚拟机栈:Java Virtual Machine Stacks,每个线程运行时所需要的内存

虚拟机栈

1.每个方法被执行时,都会在虚拟机栈中创建一个栈帧 stack frame(一个方法一个栈帧

2.Java 虚拟机规范允许 Java 栈的大小是动态的或者是固定不变的

3.虚拟机栈是每个线程私有的,每个线程只能有一个活动栈帧,对应方法调用到执行完成的整个过程

4.每个栈由多个栈帧(Frame)组成,对应着每次方法调用时所占用的内存,每个栈帧中存储着:

5.局部变量表:存储方法里的 Java 基本数据类型以及对象的引用

6.动态链接:也叫指向运行时常量池的方法引用

7.方法返回地址:方法正常退出或者异常退出的定义

8.操作数栈或表达式栈和其他一些附加信息

虚拟机栈特点:

1.栈内存不需要进行GC,方法开始执行的时候会进栈,方法调用后自动弹栈,相当于清空了数据

2.栈内存分配越大越大,可用的线程数越少(内存越大,每个线程拥有的内存越大)

方法内的局部变量是否线程安全:

  2.1如果方法内局部变量没有逃离方法的作用访问,它是线程安全的(逃逸分析)

  2.2如果是局部变量引用了对象,并逃离方法的作用范围,需要考虑线程安全

局部变量

局部变量表也被称之为局部变量数组或本地变量表,本质上定义为一个数字数组,主要用于存储方法参数和定义在方法体内的局部变量

1.表是建立在线程的栈上,是线程私有的数据,因此不存在数据安全问题

2.表的容量大小是在编译期确定的,保存在方法的 Code 属性的 maximum local variables 数据项中

3.表中的变量只在当前方法调用中有效,方法结束栈帧销毁,局部变量表也会随之销毁

4.表中的变量也是重要的垃圾回收根节点,只要被表中数据直接或间接引用的对象都不会被回收

栈中存放的资源:

操作数栈

在方法执行过程中,根据字节码指令,往栈中写入数据或提取数据,即入栈(push)或出栈(pop)

1.保存计算过程的中间结果,同时作为计算过程中变量临时的存储空间,是执行引擎的一个工作区

2.Java 虚拟机的解释引擎是基于栈的执行引擎,其中的栈指的就是操作数栈

3.如果被调用的方法带有返回值的话,其返回值将会被压入当前栈帧的操作数栈中

因此,在栈中主要存放方法调用和局部变量,并且栈中的资源数据都是私有的,不会被其他线程访问。

2.3程序计数器 (Program Counter Register

作用:内部保存字节码的行号,用于记录正在执行的字节码指令地址(如果正在执行的是本地方法则为空)

简单来讲就是记住下一条jvm指令的执行地址,并且是线程私有的。

原理:

1.JVM 对于多线程是通过线程轮流切换并且分配线程执行时间,一个处理器只会处理执行一个线程

2.切换线程需要从程序计数器中来回去到当前的线程上一次执行的行号

2.4 方法区(元空间)

方法区:是各个线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、即时编译器编译后的代码等数据,虽然 Java 虚拟机规范把方法区描述为堆的一个逻辑部分,但是也叫 Non-Heap(非堆)

方法区的大小不必是固定的,可以动态扩展,加载的类太多,可能导致永久代内存溢出 (OutOfMemoryError)

运行时常量池是方法区的一部分

1.常量池(编译器生成的字面量和符号引用)中的数据会在类加载的加载阶段放入运行时常量池

2.类在解析阶段将这些符号引用替换成直接引用

3.除了在编译期生成的常量,还允许动态生成,例如 String 类的 intern()

三:总结

堆是JVM中最大的一块内存区域,用于存储对象实例。一般通过new关键字创建的对象都存放在堆中,堆的大小可以通过启动参数进行调整。堆被所有线程共享,但是它的访问是线程不安全的,需要通过锁机制来保证线程安全。

栈用于存储方法调用和局部变量。每个线程在运行时都会有一个独立的栈,栈中的每个方法调用都会创建一个栈帧,栈帧包含了方法的参数、局部变量和返回值等信息。栈的大小是固定的,并且栈中的数据是线程私有的,不会被其他线程访问。

方法区用于存储类的信息和静态变量。它是所有线程共享的内存区域,存储了类的结构信息、常量池、静态变量和方法字节码等。方法区的大小也可以通过启动参数进行调整。

程序计数器是每个线程私有的,用于记录当前线程执行的字节码指令的地址。每个线程都有一个独立的程序计数器,用于控制线程的执行流程。

JVM内存模型的设计可以提供内存管理和线程安全的机制,同时也保证了Java程序的跨平台性。不同的内存区域有不同的作用和访问规则,合理地管理和利用这些内存区域可以提高Java程序的性能和稳定性。


最后附上Java1.7的内存模型图供大家参考学习

相关文章
|
26天前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
3天前
|
人工智能 Rust Java
10月更文挑战赛火热启动,坚持热爱坚持创作!
开发者社区10月更文挑战,寻找热爱技术内容创作的你,欢迎来创作!
352 14
|
19天前
|
存储 关系型数据库 分布式数据库
GraphRAG:基于PolarDB+通义千问+LangChain的知识图谱+大模型最佳实践
本文介绍了如何使用PolarDB、通义千问和LangChain搭建GraphRAG系统,结合知识图谱和向量检索提升问答质量。通过实例展示了单独使用向量检索和图检索的局限性,并通过图+向量联合搜索增强了问答准确性。PolarDB支持AGE图引擎和pgvector插件,实现图数据和向量数据的统一存储与检索,提升了RAG系统的性能和效果。
|
6天前
|
JSON 自然语言处理 数据管理
阿里云百炼产品月刊【2024年9月】
阿里云百炼产品月刊【2024年9月】,涵盖本月产品和功能发布、活动,应用实践等内容,帮助您快速了解阿里云百炼产品的最新动态。
阿里云百炼产品月刊【2024年9月】
|
21天前
|
人工智能 IDE 程序员
期盼已久!通义灵码 AI 程序员开启邀测,全流程开发仅用几分钟
在云栖大会上,阿里云云原生应用平台负责人丁宇宣布,「通义灵码」完成全面升级,并正式发布 AI 程序员。
|
23天前
|
机器学习/深度学习 算法 大数据
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
2024“华为杯”数学建模竞赛,对ABCDEF每个题进行详细的分析,涵盖风电场功率优化、WLAN网络吞吐量、磁性元件损耗建模、地理环境问题、高速公路应急车道启用和X射线脉冲星建模等多领域问题,解析了问题类型、专业和技能的需要。
2590 22
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
|
5天前
|
存储 人工智能 搜索推荐
数据治理,是时候打破刻板印象了
瓴羊智能数据建设与治理产品Datapin全面升级,可演进扩展的数据架构体系为企业数据治理预留发展空间,推出敏捷版用以解决企业数据量不大但需构建数据的场景问题,基于大模型打造的DataAgent更是为企业用好数据资产提供了便利。
180 2
|
3天前
|
编译器 C#
C#多态概述:通过继承实现的不同对象调用相同的方法,表现出不同的行为
C#多态概述:通过继承实现的不同对象调用相同的方法,表现出不同的行为
104 65
|
6天前
|
Linux 虚拟化 开发者
一键将CentOs的yum源更换为国内阿里yum源
一键将CentOs的yum源更换为国内阿里yum源
321 2
|
23天前
|
机器学习/深度学习 算法 数据可视化
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
2024年中国研究生数学建模竞赛C题聚焦磁性元件磁芯损耗建模。题目背景介绍了电能变换技术的发展与应用,强调磁性元件在功率变换器中的重要性。磁芯损耗受多种因素影响,现有模型难以精确预测。题目要求通过数据分析建立高精度磁芯损耗模型。具体任务包括励磁波形分类、修正斯坦麦茨方程、分析影响因素、构建预测模型及优化设计条件。涉及数据预处理、特征提取、机器学习及优化算法等技术。适合电气、材料、计算机等多个专业学生参与。
1580 17
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码