jvm----运行时数据区域

2023-10-31

先导

Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而一直存在,有些区域则是依赖用户线程的启动和结束而建立和销毁。根据《Java虚拟机规范》的规定,Java虚拟机所管理的内存将会包括以下几个运行时数据区域:

程序计数器(Program Counter Register)

PCR是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。在Java虚拟机的概念模型里  ,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,它是程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。

由于Java虚拟机的多线程是通过线程轮流切换、分配处理器执行时间的方式来实现的,在任何一
个确定的时刻,一个处理器(对于多核处理器来说是一个内核)都只会执行一条线程中的指令。因
此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存。

如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地
址;如果正在执行的是本地(Native)方法,这个计数器值则应为空(Undefined)。
此内存区域是唯一一个在《Java虚拟机规范》中没有规定任何OutOfMemoryError情况的区域。

Java虚拟机栈(Java Virtual Machine Stack)

它也是线程私有的,它的生命周期与线程相同。虚拟机栈描述的是Java方法执行的线程内存模型:每个方法被执行的时候,Java虚拟机都会同步创建一个栈帧 (Stack Frame)用于存储局部变量表、操作数栈、动态连接、方法出口等信息。每一个方法被调用直至执行完毕的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。

经常有人把Java内存区域笼统地划分为堆内存(Heap)和栈内存(Stack),而“栈”通常就是指这里讲的虚拟机栈.或者更多的情况下只是指虚拟机栈中局部变量表部分

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

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

本地方法栈(Native Method Stacks)

与虚拟机栈所发挥的作用是非常相似的,其区别只是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的本地(Native)方法服务。

Java堆(Java Heap)

对于Java应用程序来说,Java堆是虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,Java世界里“几乎”所有的对象实例都在这里分配内存。

Java堆是垃圾收集器管理的内存区域,因此一些资料中它也被称作“GC堆”(Garbage Collected
Heap,幸好国内没翻译成“垃圾堆”)。从回收内存的角度看,由于现代垃圾收集器大部分都是基于分代收集理论设计的,所以Java堆中经常会出现“新生代”“老年代”“永久代”“Eden空间”“From Survivor空间”“To Survivor空间”等名词。

如果从分配内存的角度看,所有线程共享的Java堆中可以划分出多个线程私有的分配缓冲区
(Thread Local Allocation Buffer,TLAB),以提升对象分配时的效率。不过无论从什么角度,无论如何划分,都不会改变Java堆中存储内容的共性,无论是哪个区域,存储的都只能是对象的实例,将Java堆细分的目的只是为了更好地回收内存,或者更快地分配内存。​​​​​​​

方法区(Method Area)

与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。虽然《Java虚拟机规范》中把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫作“非堆”(Non-Heap),目的是与Java堆区分开来。

说到方法区,不得不提一下“永久代”这个概念,尤其是在JDK 8以前,许多Java程序员都习惯在
HotSpot虚拟机上开发、部署程序,很多人都更愿意把方法区称呼为“永久代”(Permanent
Generation),或将两者混为一谈。本质上这两者并不是等价的,因为仅仅是当时的HotSpot虚拟机设计团队选择把收集器的分代设计扩展至方法区,或者说使用永久代来实现方法区而已,这样使得HotSpot的垃圾收集器能够像管理Java堆一样管理这部分内存,省去专门为方法区编写内存管理代码的工作。

在JDK 6的时候HotSpot开发团队就有放弃永久代,逐步改为采用本地内存(Native Memory)来实现方法的计划了  ,到了JDK 7的HotSpot,已经把原本放在永久代的字符串常量池、静态变量等移出,而到了JDK 8,终于完全废弃了永久代的概念,改用与JRockit、J9一样在本地内存中实现的元空间(Meta-space)来代替,把JDK 7中永久代还剩余的内容(主要是类型信息)全部移到元空间中。

运行时常量池(Runtime Constant Pool)

运行时常量池是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池表(Constant Pool Table),用于存放编译期生成的各种字面量与符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。

直接内存(Direct Memory)

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

jvm----运行时数据区域 的相关文章

随机推荐

  • 杂牌平板mt6797_单核强劲但耐久不足的MT6797_平板电脑评测-中关村在线

    单核强劲但耐久不足的MT6797 笔者使用安兔兔v7 0 7和Geekbench 4对酷比魔方X1进行了跑分测试 结果如下 安兔兔测试 GeekBench 4测试 根据安兔兔和GeekBench 4测试 MT6797性能尚可一战 尤其是在G
  • 【论文精度】MAE逐段精读

    跟李沐学AI的b站视频视频 论文精读笔记第四期 包含MAE论文精读第一遍和论文精读第二遍
  • 01背包问题中两个背包的解法

    问题描述大致如下 给你n个物品 两个背包 如何装包可以使得两个背包得到的价值是最大的 一个简化问题 来自微软的笔试题 题目大意 有两条生产线 一条可以工作x小时 一条工作y小时 一个数组表示每种汽车生产需要多久 要求最多生产多少种汽车 解析
  • 《Python进阶系列》十二:最全魔术方法整理

    Python中的魔术方法 所谓魔法函数 Magic Methods 是Python的一种高级语法 允许你在类中自定义函数 并绑定到类的特殊方法中 比如在类A中自定义 str 函数 则在调用str A 时 会自动调用 str 函数 并返回相应
  • Java继承(超详解)

    目录 1 继承 1 1 继承概述 1 2 继承的优缺点 1 3 继承中变量的访问特点 1 4 super 1 5 继承中构造方法的访问特点 1 6 继承中成员方法的访问特点 1 7 方法重写 1 8 方法重写的注意事项 1 9 java中继
  • 2021年南京大学842考研-软件工程部分简答题

    1 抽象和分解的关系 抽象和分解是软件设计的核心思想 分解是横向将系统分解为几个相对简单的子系统以及各子系统之间的关系 分解之后每次只需关注经过分解的相对简单的子系统及其相互间的关系 从而降低了复杂度 抽象则是在纵向上聚焦各自系统的接口 抽
  • MyBatis简介

    1 什么是 MyBatis MyBatis 是一款优秀的持久层框架 它支持自定义 SQL 存储过程以及高级映射 MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作 MyBatis 可以通过简单的 XML 或注解来
  • c++ std::string截取子串

    std vector
  • 上传文件请求绕过网关

    一 问题描述 1 本例中 我需要请求上传文件微服务的接口 并且绕过Zuul网关 因为请求会携带图片 如果再通过网关的话 会非常浪费资源 2 图片上传是文件的传输 如果也经过Zuul网关的代理 文件就会经过多次网路传输 造成不必要的网络负担
  • 【附源码】计算机毕业设计Python安卓Android的问卷调查管理系统9q4d4(源码+程序+LW+调试部署)

    附源码 计算机毕业设计Python安卓Android的问卷调查管理系统9q4d4 源码 程序 LW 调试部署 该项目含有源码 文档 程序 数据库 配套开发软件 软件安装教程 项目运行环境配置 Python3 7 7 Django Mysql
  • 【有限元分析】有限元仿真分析与解析解的结果对比——以阶梯轴的静力分析为例

    1 对一个阶梯轴零件进行基于材料力学的理论计算 求解最大应力值 2 在WORKBENCH中对该阶梯轴零件进行有限元仿真 实行两种仿真方案 分别是1 梁模型建模 梁单元网格划分 2 实体模型建模 六面体单元网格划分 观察两种仿真结果并与理论计
  • Flask导入配置文件

    为什么要导入配置文件呢 我刚开始学习Flask的时候 觉得没这必要 所以直接忽略了 后来 app的配置越来越多 并且不同的py文件里的配置有重复 所以需要另外写一个配置文件 方便管理 官方文档上说的有3种方法 app config from
  • android 拍照上传照片

    废话不多说 直接进入主题 想要在android中实现拍照最简单饿方法就是New 一个 Intent 设置Action为android media action IMAGE CAPTURE 然后使用startActivityForResult
  • 锁存器、触发器和寄存器

    锁存器 锁存器 latch 对脉冲电平敏感 在时钟脉冲的电平作用下改变状态 锁存器是电平触发的存储单元 数据存储的动作取决于输入时钟 或者使能 信号的电平值 当锁存器处于使能状态时 输出才会随着数据输入发生变化 简单地说 它有两个输入 分别
  • 使用jvisualvm进行远程监控

    使用jvisualvm进行远程监控
  • 判定表法设计测试用例

    判定表法设计测试用例 1 判定表 是分析和表达多逻辑条件下执行不同操作的工具 判定表是由条件桩 动作桩 条件项 动作项四部分组成的表格 1 条件桩 列出了所有条件 通常认为列出条件的次序无关紧要 2 动作桩 列出所有可能的操作 这些操作的排
  • SQL布尔盲注

    SQL布尔盲注 常用函数 注入步骤 1 爆数据库名称长度 2 爆库名 3 确定当前库中表的个数 4 爆表名长度 5 爆表名 6 爆表项个数 7 爆表项长度 8 爆表项 9 爆数据 常用函数 substr str from length 返回
  • Oracle 时间差计算

    Oracle 时间差计算 两个Date类型字段 START DATE END DATE 计算这两个日期的时间差 分别以天 小时 分钟 秒 毫秒 天 ROUND TO NUMBER END DATE START DATE 小时 ROUND T
  • 编译cpp_extension遇到的问题

    参考 https blog csdn net tanmx219 article details 100829920 https github com facebookresearch maskrcnn benchmark issues 25
  • jvm----运行时数据区域

    先导 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域 这些区域有各自的用途 以及创建和销毁的时间 有的区域随着虚拟机进程的启动而一直存在 有些区域则是依赖用户线程的启动和结束而建立和销毁 根据 Java