JVM的运行时数据区

server/2024/9/23 11:00:07/

之前的文章有讲过,Java 源代码文件经过编译器编译后会生成字节码文件,并且经过类加载器加载之后会交给执行引擎执行,并在执行过程中,Java会划出一片空间去存储执行期间所用到的数据,这片空间成为运行时数据区。

根据 Java 虚拟机规范的规定,运行时数据区可以分为以下几个部分:

  • 程序计数器(Program Counter Register)
  • Java 虚拟机栈(Java Virtual Machine Stacks)
  • 本地方法栈(Native Method Stack)
  • 堆(Heap)(共享)
  • 方法区(Method Area)(共享)

五部分

堆是所有线程共享的,对象的实例保存在这。几乎所有对象都会在堆中分配。

但随着 JIT编译器的发展和逃逸技术的逐渐成熟,所有的对象都分配到堆上渐渐变得不那么“绝对”了。从 JDK 7 开始,Java 虚拟机已经默认开启逃逸分析了,意味着如果某些方法中的对象引用没有被返回或者未被外面使用(也就是未逃逸出去),那么对象可以直接在栈上分配内存。

方法区

类的信息,包括类的方法代码,变量名,方法名,访问权限,返回值等等。例如,我们调用getName方法 来获取类的名,数据来自于方法区。

方法区是一个逻辑区域,不同JDK有不同的规范。

 

 

 可以看到,不同JDK版本,方法区的内容是不同的。

在JDK1.6时,常量池全都放进方法区之中。

但是在JDK1.7的时候,字符串常量池单独剥离出来,放进了堆中,并且此时方法区被称为永久代。方法区和永久代的关系就像是 Java 中接口和类的关系,类实现了接口,接口还是那个接口,但实现已经完全升级了。

JDK8之后,方法区废除了永久代,取而代之的时元空间的概念。

为什么取消永久代,而用元空间进行替换?

旧版的 Hotspot 虚拟机是没有 JIT 的,而 Oracle 旗下的另外一款虚拟机 JRocket 是有的,那为了将 Java 帝国更好的传下去,Oracle 就想把庶长子 JRocket 的 JIT 技术融合到嫡长子 Hotspot 中。

但 JRockit 虚拟机中并没有永久代的概念,因此新的 HotSpot 索性就不要永久代了,直接占用操作系统的一部分内存好了,并且把这块内存取名叫做元空间。

元空间的大小不再受限于 JVM 启动时设置的最大堆大小,而是直接利用本地内存,也就是操作系统的内存。有效地解决了 OutOfMemoryError 错误。

 值得注意的是,当元空间的数据增长时,JVM 会请求操作系统分配更多的内存。但是如果也会发生内存溢出的问题。

虚拟机栈

虚拟机栈中保存的时虚拟机中的执行的方法的栈帧。每有一个方法被调用,其栈帧就会被压入虚拟机栈中。当方法执行结束,栈帧就会被弹出从虚拟机栈中。

注意:

虚拟机栈是每个线程独有的,不共享。

此外,虚拟机栈是会发生栈溢出的问题的。如果发生将会抛出 StackOverflowError。

本地方法栈

本地方法栈和虚拟机栈类似,只不过虚拟机栈对应的方法是虚拟机中的方法,而本地方法栈 对应的是虚拟机用到的本地Native方法。

程序计数器

程序计数器记录的是下一条指令的地址。他所占的内存比较小。像分支、循环、跳转、异常处理、线程恢复等功能都需要依赖这个计数器来完成。

在线程并发的环境中,如果是单核,那么在同一时间,只能处理一个线程。如果时间片到期,就需要切换线程,这个线程的切换就需要程序计数器。另外,为了线程切换后能恢复到正确的执行位置,每个线程都需要有一个独立的程序计数器,并且不能互相干扰,否则就会影响到程序的正常执行次序。

也就是说,我们要求程序计数器是线程私有的

字符串常量池

 之前在方法区中提到了字符串常量池,和运行时常量池(就是图中JDK1.7之后的常量池)。我们来看一下。它的作用是存放字符串常量,也就是我们在代码中写的字符串。依然在堆中。

运行时常量池

就是字节码文件的资源仓库。在运行时,JVM 会将字节码文件中的常量池加载到内存中,存放在运行时常量池中。 常量池是在字节码文件中,而运行时常量池在元空间当中。


http://www.ppmy.cn/server/19999.html

相关文章

C语言 | Leetcode C语言题解之第48题旋转图像

题目&#xff1a; 题解&#xff1a; void swap(int* a, int* b) {int t *a;*a *b, *b t; }void rotate(int** matrix, int matrixSize, int* matrixColSize) {// 水平翻转for (int i 0; i < matrixSize / 2; i) {for (int j 0; j < matrixSize; j) {swap(&matr…

vue3 ——笔记 (表单输入,监听器)

表单输入 在Vue 3中&#xff0c;v-model指令的用法稍有不同于Vue 2。在Vue 3中&#xff0c;v-model指令实际上是一个语法糖&#xff0c;它会自动将value属性和input事件绑定到组件或元素上&#xff0c;以实现双向数据绑定。 在自定义组件中使用v-model时&#xff0c;需要在组…

【Pytorch】(十三)模型部署: TorchScript

文章目录 &#xff08;十三&#xff09;模型部署: TorchScriptPytorch动态图的优缺点TorchScriptPytorch模型转换为TorchScripttorch.jit.tracetorch.jit.scripttrace和script的区别总结trace 和script 混合使用保存和加载模型 &#xff08;十三&#xff09;模型部署: TorchScr…

iOS(Object C) 插入排序

插入排序的思想: 可以想象你在打牌,手里有一张牌2, 第一次摸到一张牌5; 5 比1 大,所以摸到的牌5放在1的右边; (此时手里的牌为 2->5) 第二次摸到一张牌3; 3比5小,所以3和5互换位置,再拿3和2比,3比2大,3不动(此时手里的牌为 2-> 3 -> 5) 第三次摸到一张牌1,1比5小,…

前端学习<四>JavaScript——54-原型链

常见概念 构造函数 构造函数-扩展 原型规则和示例 原型链 instanceof 构造函数 任何一个函数都可以被 new&#xff0c;new 了之后&#xff0c;就成了构造方法。 如下&#xff1a; function Foo(name, age) {this.name name;this.age age;//retrun this; //默认有这…

react 遇到的问题1 ——( 数据更新视图没更新)已解决

问题&#xff1a; 使用react开发项目时&#xff0c;使用useState 定义数据&#xff0c;通过定义的set方法修改数据&#xff0c;视图没有更新 原因&#xff1a; 在 React 中使用 useState 定义数据时&#xff0c;useState 返回一个数组&#xff0c;包含当前状态和更新的函数。…

【学习】软件测试自动化,是未来的趋势还是当前的必需

在当今快速迭代的软件开发周期中&#xff0c;速度和质量成为了企业生存的关键。随着DevOps实践的普及和持续集成/持续部署&#xff08;CI/CD&#xff09;流程的标准化&#xff0c;软件测试自动化已经从未来的趋势转变为当前的必要性。本文将探讨自动化测试的现状、必要性以及其…

ICCV 2021 | FcaNet: Frequency Channel Attention Networks 中的频率分析

ICCV 2021 | FcaNet: Frequency Channel Attention Networks 中的频率分析 论文&#xff1a;https://arxiv.org/abs/2012.11879代码&#xff1a;https://github.com/cfzd/FcaNet 文章是围绕 2D 的 DCT 进行展开的&#xff0c;本文针对具体的计算逻辑进行梳理和解析。 f ( u ,…