当前位置: 首页 > news >正文

JVM-运行时数据区

目录

什么是运行时数据区?

方法区

程序计数器

虚拟机栈

局部变量表    

操作数栈       

动态连接

运行时常量池

方法返回地址

附加信息

本地方法栈

总结:


什么是运行时数据区?

     Java虚拟机在执行Java程序时,将它管理的内存分为不同的区域。这些区域用途不同,创建和销毁的时间也不同。有的随虚拟机进程启动一直存在,有的依赖用户线程启动和结束而创建和销毁。根据《Java虚拟机规范》,Java虚拟机管理的内存区域包括以下几个运行时数据区域。

来自《深入理解Java虚拟机(第3版)》

方法区

        方法区用于存储已被虚拟机加载的类型信息,常量,静态变量,即时编译器编译后的代码缓存等数据。可以理解为被线程共享的内存区域。
         根据《Java虚拟机规范》的规定,如果方法区无法满足新的内存分配需求时,将抛出
OutOfMemoryError异常。

        Java堆(Java heap)是虚拟机管理的最大一块内存,线程共享,虚拟机启动时创建,用于存储对象实例。虽然在《Java虚拟机规范》中对Java堆的描述是:“所有 的对象实例以及数组都应当在堆上分配”,但随着即时编译技术的发展,栈上分配,标量替换等优化手段,Java实例不仅仅分配在堆上。

        Java堆是垃圾回收的主要区域,HotSpot VM 的堆内存又分为新生代、老年代和永久代。新生代又分为Eden空间和Survivor空间。 常见的垃圾收集器也都是围绕这些内存区域进行工作的。将Java堆细分,主要是为了更好的回收内存或更快分配内存。

        根据《Java虚拟机规范》的规定,Java堆可以处于物理上不连续的内存空间中,但在逻辑上应是连续的,就像我们使用磁盘空间存储文件一样,并不要求所有文件连续存放。但对于大对象(典型的如数组对象),多数虚拟机实现出于实现简单、存储高效的考虑,很可能会要求连续的 内存空间。

        Java堆既可以被实现成固定大小的,也可以是可扩展的,不过当前主流的Java虚拟机都是按照可扩展来实现的(通过参数-Xmx和-Xms设定)。如果在Java堆中没有内存完成实例分配,并且堆也无法再扩展时,Java虚拟机将会抛出OutOfMemoryError异常。

程序计数器

      因为Java虚拟机中的多线程通过线程轮流切换、分配处理器的执行时间的方式实现,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)都只会执行一条线程中的指令。为了在线程切换后准确恢复到正确的执行位置,需要记录每个线程的所执行的字节码的行号,这时就需要程序计数器。

      程序计数器是一块较小的内存,每个线程都需要一个独立的程序计数器,每个线程之间程序计数器互不影响,独立存储,是“线程私有”的内存。在Java虚拟机的概念模型里,通过改变程序计数器的值选取下一条需要执行的字节码指令。程序计数器,是程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础都需要依赖这个计数器完成。大家会想到程序在计算机上执行过程中的程序技术器,决定着程序执行的流程。

       如果执行的是本地(Native)方法,程序计数器的值则应为空(undefined),此区域是为一个一个在《Java虚拟机规范》中没有任何OutOfMemeoryError情况的区域

虚拟机栈

        Java虚拟机栈,也是线程私有的,和线程的生命周期相同。

        每个方法被执行时,Java虚拟机会同步创建一个栈帧,每个方法被调用直至执行完毕的过程,就对应着一个栈帧在虚拟机栈中刚从入栈到出栈的过程。

栈帧由几部分组成?

      局部变量表,操作数栈,方法返回地址,动态连接,附加信息等。

局部变量表    

        我们知道方法由:访问修饰符(可选),返回值,方法名,参数列表,方法体组成。

        局部变量表,保存方法参数和方法内部的局部变量,在局部变量表中的存储空间以变量槽(slot)为单位,每个槽都应该能存放一个boolean,byte,char,short,int,float,reference或returnAddress类型的数据,这8种数据类型都可以使用32位或更小的物理内存累存储,且随着处理器、操作系统或虚拟机实现的不同而发生变化。局部变量表的空间在编译期即可根据源码和虚拟机的具体栈内存实现方式确定,不会受程序运行时数据的影响。

操作数栈       

        操作数栈,是一个先进后出的栈结构,用于临时保存方法执行过程的操作数。比如在进行加法运算:1+2=3时。

1. 将第一个操作数 1 压入操作数栈;

2. 将第二个操作数 2 压入操作数栈;

3. 从操作数栈弹出第二个操作数 2;

4. 从操作数栈弹出第一个操作数 1;

5. 将两个操作数相加得到结果 3;

6. 将结果 3 压入操作数栈;

7. 从操作数栈弹出结果 3;

       通过操作数栈,虚拟机可以方便地对运算中的操作数进行入栈和出栈,实现复杂的算术运算逻辑。它避免了每次运算都需要在堆内存中分配新的操作数对象,可以提高执行效率。高效地对方法运算过程中的操作数进行入栈出栈操作,这是实现Java虚拟机高效运行的重要组成部分。每个栈帧的操作数栈的深度,在编译器也可确定,在运行期间不会变。

动态连接

        在讲动态连接之前,我们先回顾一下运行时常量池的知识。

运行时常量池

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

        Class文件的常量池中存在大量的符号引用,字节码中的方法调用指令就以常量池里指向方法的符号引用作为参数。这些符号引用一部分会在类加载阶段或者第一次使用的时候被转为直接引用,这种转化被称为静态解析。另一部分将在每次运行期间都转化为直接引用,这部分称为动态连接。

        动态连接是指在程序运行时才去解析字节码中的符号引用,并把符号引用替换为直接引用的过程,主要为了支持Java动态绑定机制。动态绑定允许程序运行时才去决定实际调用的方法,给Java带来很大的灵活性,支持Java的多态特性。

举个例子:

public class Main {public static void main(String[] args) {Animal a = new Dog(); a.run();}
}class Animal {public void run() {System.out.println("Animal is running");}
}class Dog extends Animal {@Overridepublic void run() {System.out.println("Dog is running"); }
}

        编译时,编译器只知道a是一个Animal对象,它不知道a最终会指向一个Dog对象。

        运行时,JVM通过动态连接,才会根据实际的对象类型Dog,动态地绑定到Dog.run()这个方法上,从而输出"Dog is running"。如果没有动态连接,那么只能静态地绑定到Animal.run(),就无法利用多态的特性了。所以动态连接是支持运行时多态以及动态绑定的关键。它让Java语言可以更灵活地处理对象的多态特性。       

方法返回地址

        方法执行完退出时,无论是遇到方法返回的字节码指令还是遇到异常退出,都需要返回到最初方法被调用的位置,程序才能继续执行。这个位置就是方法返回地址。

例如:

public int sum(int a, int b) {return a + b;
}public static void main(String[] args) {int s = sum(1, 2);System.out.println(s);
}

        在main方法调用sum方法时,会先记录下 “int s = sum(1,2);” 这行代码的位置,当sum方法执行完返回结果后,返回到该位置,执行后面的“System.out.pringln(s);”方法。所以,方法返回地址,就是调用该方法的具体代码位置。

        JVM通过动态连接找到方法的入口,并记录下返回地址,以便在方法执行后正确返回到调用方。返回地址是实现正确的方法调用流程所必需的。动态连接使得返回地址可以在运行时确定,这样Java程序才可以实现动态绑定和灵活的函数调用机制。 

        而方法返回后,该方法对应的栈帧会出栈,栈顶的栈帧就是该方法的调用者,调用者的局部变量表可能会发生变化,这取决于方法的返回值是否被赋值给了调用者栈帧的某个局部变量。还以上面的方法为例,当sum方法执行完返回后,main方法栈帧的局部变量s被赋值为sum方法的返回值3。

附加信息

        附加信息,是指在进行方法调用时,除了明确的参数和返回值之外,还可以传递的一些额外信息。从理论上讲,它提供了一种传递方法调用的额外上下文的方式,对JVM内部来说可以提供更多信息。一些专业的程序分析和追踪工具可能会用到它们,对日常开发影响不大。

本地方法栈

        本地方法栈(Native Method Stack):与虚拟机栈类似,用于支持Native方法的执行。关于本地方法,可参考Java本地方法/Java native方法/JNI_jni native方法_小王师傅66的博客-CSDN博客

总结:

        JVM运行时数据区主要包括:方法区,堆,虚拟机栈,程序计数器,本地方法栈。

        方法区(Method Area):用于存储类信息、静态变量、静态方法等数据,可以理解为所有线程共享的内存区域。方法区无法满足新的内存分配需求时,会抛出OutOfMemeoryError异常;
        堆内存(Heap):用于存储对象实例,可以理解为所有线程共享的内存区域。如果在Java堆中没有内存完成实例分配,并且堆也无法再扩展时,Java虚拟机将会抛出OutOfMemoryError异常。可以通过调整-Xms和-Xmx参数调整堆空间;
        虚拟机栈(VM stack):用于存储局部变量表、操作栈、动态链接、方法返回地址/方法出口等信息,属于线程私有。每个线程都有自己的虚拟机栈。当线程请求的栈深度超过虚拟机所允许的最大深度时,就会抛出 StackOverflowError 异常。当虚拟机栈的空间无法分配时,将抛出 OutOfMemoryError 异常。可以通过调整-Xss参数调整栈空间;
        程序计数器(PC Register):用于存储指向下一条将要执行的指令的地址,每个线程都有自己的程序计数器,它的空间是非常小的,基本不会发生溢出的情况。
        本地方法栈(Native Method Stack):与虚拟机栈类似,用于支持Native方法的执行。本地方法栈也是线程私有,与虚拟机栈一样,本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常。

相关文章:

JVM-运行时数据区

目录 什么是运行时数据区? 方法区 堆 程序计数器 虚拟机栈 局部变量表 操作数栈 动态连接 运行时常量池 方法返回地址 附加信息 本地方法栈 总结: 什么是运行时数据区? Java虚拟机在执行Java程序时,将它管…...

RedisTemplate中boundHashOps的使用

1、往指定key中存储 键值 redisTemplate.boundHashOps("demo").put("1",1); 2、根据指定key中得键取出值 System.out.println(redisTemplate.boundHashOps("demo").get("1")); 3、根据指定key中得键删除 redisTemplate.boundHash…...

计算机网络-性能指标

计算机网络-性能指标 文章目录 计算机网络-性能指标简介速率比特速率 带宽吞吐量时延时延计算 时延带宽积往返时间网络利用率丢包率总结 简介 性能指标可以从不同的方面来度量计算机网络的性能 常用的计算机网络的性能指标有以下8个 速率带宽吞吐量时延时延带宽积往返时间利…...

排序第一课【插入排序】直接插入排序 与 希尔排序

目录 1. 排序的概念: 2.插入排序基本思想 3.直接插入排序 4.希尔排序 1. 排序的概念: 排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。 稳定性&#xf…...

云计算——ACA学习 云计算概述

作者简介:一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭:低头赶路,敬事如仪 个人主页:网络豆的主页​​​​​ 目录 写在前面 上章回顾 本章简介 本章目标 一.云计算产生背景 1.信息时代的重点变革…...

如何为网站进行全面的整站翻译?

要翻译整个网站,可以按照以下步骤进行: 确定翻译需求:确定你需要将整个网站翻译成哪种语言。这可以根据你的目标受众和市场进行决定。 寻找翻译资源:你可以选择以下几种方式来进行网站翻译: a. 人工翻译:雇…...

项目部署(前后端分离)

1、前端项目 (打包成dist文件,放到nginx的html目录下面),然后配置nginx 2、后端项目部署 使用之前的shell脚本(然后赋予用户权限),最后运行脚本 查看进程...

增强型Web安全网关在银行的应用

销售,绝不是降低身份去取悦客户,而是像朋友一样给予合理的建议。你刚好需要,我刚好专业!仅此而已! 乔.吉拉德 健康的安全体系,还可以更完善 浙江某商业银行股份有限公司是一家成立多年的商业银行&#xf…...

Oracle-ORA-00600:[ktspffbmb:objdchk_kcbnew_3]

问题背景: 应用执行存储过程报错ORA-00600: 内部错误代码, 参数: [ktspffbmb:objdchk_kcbnew_3], [0], [3303775], [4], [], [], [], [], [], [], [], [],导致过程无法正常执行 ORA-00600: 内部错误代码, 参数: [ktspffbmb:objdchk_kcbnew_3], [0], [3303775], [4]…...

SPINN:基于设备和云的神经网络协同递进推理

SPINN:基于设备和云的神经网络协同递进推理 论文标题:SPINN: synergistic progressive inference of neural networks over device and cloud 原文链接:https://dl.acm.org/doi/10.1145/3372224.3419194 论文动机 现代CNN过多的计算需求&am…...

数据结构-二叉树

数据结构-二叉树 二叉树的概念二叉树的遍历分类 建立二叉树,并遍历二叉树的最小单元二叉树的最小单元初始化初始化二叉树前序遍历的实现中序遍历的实现后序遍历的实现计算节点的个数计算树的深度求第k层的个数查找二叉树的元素分层遍历 全部代码如下 二叉树的概念 二…...

Open3D 进阶(4)高斯混合点云聚类

目录 一、算法原理1、原理概述2、实现流程3、参考文献二、代码实现三、结果展示四、测试数据本文由CSDN点云侠原创,原文链接。爬虫网站自重。 一、算法原理 1、原理概述 高斯混合聚类(GMM)算法假设数据点是由一个或多个高斯分布生成的,并通过最大似然估计的方法来估计每个簇…...

计算机组成和IO

文章目录 计组和Epoll:计算机组成原理:网络数据接收的流程:内核如何管理socket以及状态的更新select系统调用的复杂度epoll的et和lt模式及java的选择 国内访问chatai就可以 https://aiweb.douguguo.com/?typeadd计组和Epoll: 计…...

STM32CUBUMX配置RS485 modbus STM32(从机)亲测可用

———————————————————————————————————— ⏩ 大家好哇!我是小光,嵌入式爱好者,一个想要成为系统架构师的大三学生。 ⏩最近在开发一个STM32H723ZGT6的板子,使用STM32CUBEMX做了很多驱动&#x…...

系统设计类题目汇总

1 设计一个系统统计当前时刻北京用户在线人数 【Redis】位图以及位图的使用场景(统计在线人数和用户在线状态) 1.1 方案一: 在用户登录时,使用 Redis SET 将用户 ID 添加到一个特定的键(例如 “online:beijing”)。用户退出时&…...

css滚动条样式指南

css滚动条样式指南 滚动条是网页设计中经常被忽视的元素。虽然它看起来像是一个小细节,但它在网站导航中起着至关重要的作用。默认的滚动条可能看起来不合适,有损整体美观。本文将介绍如何使用 CSS 自定义滚动条。 在 Chrome、Edge 和 Safari 中设置滚…...

vue子组件修改父组件传递的变量(自定义日期时间组件,时间间隔为15分钟或者一个小时)

vue子组件修改父组件传递的变量 子组件不能直接修改父组件变量的值,但是可以通过调用父组件的方法来修改。 实现步骤 在父组件声明变量 export default {data() {return {startTime:"",......},......} }在父组件使用子组件并传递数据,修改…...

【PyTorch】nn.Conv2d函数详解

nn.Conv2d 是 PyTorch 中的一个卷积层,用于实现二维卷积操作 torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride1, padding0, dilation1, groups1, biasTrue, padding_modezeros, deviceNone, dtypeNone )参数解释 in_channels:输入的通…...

数智保险 创新未来 | GBASE南大通用亮相中国保险科技应用高峰论坛

本届峰会以“数智保险 创新未来”为主题,GBASE南大通用携新一代创新数据库产品及金融信创解决方案精彩亮相,与国内八百多位保险公司高管和众多保险科技公司技术专家,就保险领域数字化的创新应用及生态建设、新一代技术突破及发展机遇、前沿科…...

分布式天梯图算法在 Redis 图数据库中的应用

分布式天梯图算法在 Redis 图数据库中的应用 一、简介1 天梯图算法2 天梯图算法在Redis的应用 二、Redis分布式天梯图算法设计与优化1 基于天梯图的分布式算法设计2 多节点扩展与负载均衡优化3 数据存储方案与压缩策略 三、技术实现3.1 系统架构设计3.2 技术选型3.3 关键实现细…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

【JVM】- 内存结构

引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...

MMaDA: Multimodal Large Diffusion Language Models

CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...

ios苹果系统,js 滑动屏幕、锚定无效

现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...

.Net Framework 4/C# 关键字(非常用,持续更新...)

一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

docker 部署发现spring.profiles.active 问题

报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...

MySQL账号权限管理指南:安全创建账户与精细授权技巧

在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则&#xf…...