【JVM】运行时数据区域
文章目录
- 说明
- 程序计数器
- 虚拟机栈
- 本地方法栈
- Java堆
- 方法区
- 运行时常量池
- 直接内存
说明
Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而一直存在,有些区域则是依赖用户线程的启动和结束而建立和销毁。如下图,这篇文章简单介绍下各个区域的作用

程序计数器
程序计数器(Program Counter,简称PC)是Java虚拟机(JVM)中的一块内存区域,它是一种较小的、无法被线程切换所影响的内存空间。每个线程都有自己独立的程序计数器,用于存储当前线程执行的字节码指令的地址。
程序计数器在JVM中有以下几个主要作用:
- 线程控制:程序计数器指示了每个线程将要执行的指令地址。在线程切换时,JVM能够恢复到正确的执行点。
- 字节码解释器:在Java中,代码被编译成字节码(bytecode)。程序计数器用于跟踪当前执行的字节码指令,以便字节码解释器能够逐条执行指令。
- 异常处理:当Java程序抛出异常时,JVM会根据异常处理表来确定异常处理代码的位置。程序计数器在这里发挥了关键作用,帮助JVM准确位处理代码的位置。
- 线程私有:每个线程都有自己独立的程序计数器。这使得线程能够独立执行,不受其他线程影响。
简单来说程序计数器就是下一条指令要执行的地址,每个线程都会具有,线程私有。
虚拟机栈
虚拟机栈(Virtual Machine Stack)是Java虚拟机(JVM)为每个线程私有创建的一块内存区域,用于存储方法执行过程中的局部变量、操作数栈、动态链接和方法出口等信息。每个方法在执行时都会创建一个栈帧(Stack Frame)并入栈,方法执行完毕后栈帧出栈。栈帧包含了方法的局部变量、操作数栈、返回地址等信息。
虚拟机栈具有以下几个主要特点:
- 线程私有:每个线程都有自己独立的虚拟机栈,这保证了多线程环境下方法的执行状态不会相互干扰。
- 方法调用:虚拟机栈用于保存方法调用的状态。每次方法调用时,会在虚拟机栈上创建一个栈帧,栈帧包含了方法的局部变量、操作数栈等信息。
- 局部变量和操作数栈:栈帧内部包含局部变量表和操作数栈。局部变量表用于存储方法中的局部变量,而操作数栈用于执行操作码(字节码指令)时的临时存储。
- 异常处理:虚拟机栈也参与异常处理机制。当方法内部发生异常而未被捕获时,虚拟机会查找虚拟机栈来定位异常发生的位置,以便于异常处理。
需要注意的是,虚拟机栈的大小是可以配置的,并且栈空间有可能会发生栈溢出(Stack Overflow)异常。栈溢出通常是由于递归调用深度过大或者局部变量表和操作数栈占用的空间过大导致的。
简单来说每个方法就对应一个栈帧,方法调用和执行就代表了栈帧的出栈和入栈操作,栈帧里面就存放了方法的一些必要信息。
本地方法栈
本地方法栈(Native Method Stack)与虚拟机栈类似,是Java虚拟机为执行本地方法(Native Method)而准备的一块内存区域。本地方法指的是用非Java语言(通常是C、C++等)编写的方法,这些方法可以通过Java的本地接口(JNI,Java Native Interface)在Java程序中调用。
本地方法栈是为了支持Java程序与非Java本地方法之间的交互而存在的内存区域,类似于虚拟机栈,但用于本地方法的调用和执行。
Java堆
当我们在编写Java程序时,所有的对象实例(比如类的实例、数组等)都需要在内存中存储。Java堆就是用来存储这些对象的地方。它是一个非常大的内存区域,被所有线程共享。
关键点如下:
-
对象存储:每次使用
new关键字创建一个对象时,这个对象都会被分配到Java堆中。无论是我们自己定义的类,还是Java内置的类,都会在堆上分配内存。 -
垃圾回收:Java堆是被垃圾回收器管理的。当一个对象不再被程序引用,也就是没有变量指向它时,垃圾回收器会回收这个对象所占用的内存,以便为将来的对象分配空间。
-
分代结构:Java堆通常被划分为不同的“代”,比如新生代和老年代。新创建的对象会被分配到新生代,而存活时间较长的对象会被移到老年代。这种分代结构有助于提高垃圾回收的效率。
-
内存设置:我们可以通过命令行参数来设置Java堆的初始大小和最大大小。这可以帮助我们优化程序的内存使用。
-
内存溢出:如果我们的程序创建了过多的对象,超过了堆的可用空间,就会引发内存溢出错误,导致程序崩溃。
总之,Java堆是用来存储Java程序中的对象的内存区域,垃圾回收器会在这里管理对象的分配和释放,从而保持程序的正常运行。
方法区
方法区(Method Area)是Java虚拟机中的一块内存区域,用于存储类的元数据信息、静态变量、常量池、方法代码等。它是所有线程共享的,与堆一样,也是Java虚拟机的一部分。
以下是关于方法区的一些要点:
-
元数据信息:方法区主要用于存储类的元数据信息,包括类的名称、访问修饰符、字段信息、方法信息等。这些信息在运行时被Java虚拟机使用,例如在类加载、字节码解析和方法调用等时候。
-
静态变量:静态变量,也叫类变量,被存储在方法区中。这些变量在类加载的过程中被创建并分配内存,它们在整个类的生命周期内保持不变。
-
常量池:常量池是一种存储在方法区中的数据结构,用于存放编译时生成的各种字面量和符号引用。它包括字符串常量、类和接口的全限定名、字段和方法的名称和描述符等信息。
-
方法代码:方法区也存储类的方法代码。这些代码在类被调用时被执行。方法区中存储的方法字节码被解释器或者即时编译器(如HotSpot的C2编译器)执行。
-
运行时常量池:在Java 7 及之前的版本,常量池也包括一部分运行时生成的常量。但从Java 8 开始,运行时常量池已经被移到堆中的一部分,称为运行时常量池。
-
内存溢出:方法区内存溢出错误通常被称为“永久代溢出”,这是因为在Java 7 及之前的版本中,方法区被实现为持久代。随着类加载和卸载的不断进行,方法区的空间也会被耗尽,导致程序崩溃。
需要注意的是,从Java 8 开始,方法区被元空间(Metaspace)所取代。元空间使用的是本地内存而非虚拟机内存,因此它更加灵活,避免了持久代溢出等问题。
总之,方法区是存储类的元数据、静态变量、常量池和方法代码等信息的内存区域,是Java虚拟机重要的组成部分之一。
运行时常量池
当Java类文件被加载到内存中时,会创建一个运行时常量池(Runtime Constant Pool),它是类中常量的一种运行时表示。运行时常量池包含了从类文件的编译时常量池中提取出来的一部分内容,以及在运行时生成的常量。
编译时常量池是位于类文件中的,它包含了类中的各种常量,如字符串、数字、类名、方法名等。而运行时常量池是在类加载时被构建的,用于在程序运行期间支持常量的引用和操作。
运行时常量池不仅包含编译时常量池中的内容,还可能包括一些在运行时生成的常量。例如,字符串拼接的结果、动态方法调用等都可以在运行时常量池中得到体现。
需要注意的是,从Java 8 开始,常量池被移到元空间(Metaspace)中,取代了之前的永久代。元空间具有更大的灵活性,不再受到固定大小的限制。在这种情况下,运行时常量池仍然存在,但它与常量池的管理方式有所不同。
总之,运行时常量池是在类加载后构建的一种数据结构,包含了编译时常量池中的部分内容以及在运行时生成的常量,它为Java程序提供了常量引用和操作的支持。
直接内存
当我们在Java程序中使用内存时,通常会涉及到Java堆内存、栈内存等。而直接内存是一种与传统内存管理方式不同的内存分配方式,主要用于提高I/O操作的性能和效率。直接内存是一种用于提高I/O操作性能的内存分配方式,在Java NIO库中得到广泛应用。虽然它可以提供一些性能优势,但需要开发者自行管理分配和释放,以避免潜在的风险。
传统的Java内存管理方式中,Java堆内存的分配和释放都由JVM的垃圾回收机制进行管理。但是在一些特定场景下,特别是涉及到I/O操作的时候,传统的内存管理方式可能会导致性能问题。这时,直接内存可以作为一个媒介,充当了Java程序和操作系统之间的桥梁,以提高性能和效率。
传统的Java堆内存分配方式涉及以下步骤:
- 应用程序到Java堆内存的拷贝:当数据从应用程序传递到Java堆内存时,需要进行数据拷贝。
- Java堆内存到操作系统的拷贝:当执行I/O操作时,数据需要从Java堆内存复制到操作系统的内核缓冲区。
- 操作系统到Java堆内存的拷贝:I/O操作完成后,数据又需要从操作系统的内核缓冲区复制回Java堆内存。
而使用直接内存的情况下:
- 应用程序到直接内存的拷贝:当数据从应用程序传递到直接内存时,不需要进行数据拷贝,数据直接存储在直接内存中。
- 直接内存到操作系统的拷贝:当执行I/O操作时,数据可以直接从直接内存传递给操作系统的内核缓冲区,避免了数据复制。
- 操作系统到直接内存的拷贝:I/O操作完成后,数据可以直接从操作系统的内核缓冲区传递回直接内存,同样避免了数据复制。
当执行I/O操作时,数据可以直接从直接内存传递给操作系统的内核缓冲区,避免了数据复制。
3. 操作系统到直接内存的拷贝:I/O操作完成后,数据可以直接从操作系统的内核缓冲区传递回直接内存,同样避免了数据复制。
总之,使用直接内存可以减少数据在内存之间的复制,从而提高I/O操作的性能。这种方式特别适用于需要频繁进行大量I/O操作的场景,例如文件读写、网络传输等。然而,需要注意的是,直接内存的管理需要开发者自行负责,如果管理不当,可能会导致内存泄漏和其他问题。
相关文章:
【JVM】运行时数据区域
文章目录 说明程序计数器虚拟机栈本地方法栈Java堆方法区运行时常量池直接内存 说明 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而一直…...
uniapp踩坑合集
1、onPullDownRefresh下拉刷新不生效 pages.json对应的style中enablePullDownRefresh设置为true,开启下拉刷新 {"path" : "pages/list/list","style" :{"navigationBarTitleText": "页面标题名称","enable…...
再JAVA中如何使用qsort对类进行排序?
目录 结论: 解析: 结论: import java.util.Arrays;class Person implements Comparable<Person>{public String name;public int age;public Person(String name, int age) {this.name name;this.age age;}Overridepublic Stri…...
docker安装clickhouse
安装 docker安装 创建clickhouse目录 mkdir -P /data/clickhouse/datamkdir -P /data/clickhouse/confmkdir -P /data/clickhouse/log 拉取镜像 这里直接拉取最新镜像, 如果需要某个特定版本, 则再拉取的时候指定版本号即可. docker pull clickhouse/clickhouse-server 启动临…...
解决`idea`中`database`工具查询起别名乱码问题
文章目录 解决idea中database工具查询起别名乱码问题场景复现如何解决方式一 设置编码方式二:修改字体 原因说明 解决idea中database工具查询起别名乱码问题 场景复现 使用Idea做查询的并且起别名出现了中文乱码 如何解决 方式一 设置编码 settings->输入框输…...
UE4/5Niagara粒子特效之Niagara_Particles官方案例:1.5->2.3
目录 之前的文章: 1.5 Blend Attributes by Value 发射器更新 粒子生成 粒子更新 2.1 Static Beams 编辑 发射器更新: 粒子生成 粒子更新 2.2 Dynamic Beams 没有开始模拟前的效果是: 开始模拟后的效果是: 发射器更新 …...
Docker 容器数据卷
Docker挂载主机目录访问如果出现cannot open directory .: Permission denied 解决办法:在挂载目录后多加一个--privilegedtrue参数即可 如果是CentOS7安全模块会比之前系统版本加强,不安全的会先禁止,所以目录挂载的情况被默认为不安全的行…...
STM32--MPU6050与I2C外设
文章目录 前言MPU6050参数电路MPU6050框图 IIC外设框图 IIC的基本结构软件IIC实现MPU6050硬件IIC实现MPU6050 前言 在51单片机专栏中,用过I2C通信来进行实现AT24C02的数据存储; 里面介绍的是利用程序的编程来实现I2C的时序,进而实现AT24C02与…...
项目管理实战笔记1:项目管理常识
序 看了下极客时间的《项目管理实战》,觉得跟之前学习PMP的标准资料还是有所侧重。重新整理下,相比书上繁杂的知识,这个更通俗易懂。 1 角色转换:三大误区 误区1:事必躬亲 自己做事情是可控的,做项目依赖…...
时序分解 | MATLAB实现基于SVMD逐次变分模态分解的信号分解分量可视化
时序分解 | MATLAB实现基于SVMD逐次变分模态分解的信号分解分量可视化 目录 时序分解 | MATLAB实现基于SVMD逐次变分模态分解的信号分解分量可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 SVMD分解算法,分解结果可视化,MATLAB程序ÿ…...
阿里云访问端口被限制解决方法记录
阿里云服务器,80端口可以访问,但是加入了安全组端口8080 通过公网访问改端口策略,发现不能被访问 问题出在防火墙,需要重置一下 解决方法: 在运行的服务器上执行如下命令: # iptables -A INPUT -j ACCEP…...
antd5源码调试环境启动(MacOS)
将源码下载至本地 这里antd5 版本是5.8.3 $ git clone gitgithub.com:ant-design/ant-design.git $ cd ant-design $ npm install $ npm start前提:安装python3、node版本18.14.0(这是本人当前下载的版本) python3安装教程可参考:https://…...
单片机使用基于时间片轮询系统的-状态机-[1]
目的:【1】用C实现一个超轻量化任务管理系统 【2】具有任务suspend, resume, runonce ,auto loop ,task_delay功能 【3】易于移植,不涉及硬件底层。 示例例码: 利用switch case结构实现了单一层的 task_delay功能。弊端就是switch..case不…...
前端开发怎么解决性能优化的问题? - 易智编译EaseEditing
前端性能优化是确保网站或应用在加载速度、响应性和用户体验等方面达到最佳状态的关键任务。以下是一些解决前端性能优化问题的方法: 压缩和合并代码: 压缩和合并CSS、JavaScript和HTML文件可以减少文件大小,加快加载速度。使用压缩工具&am…...
共享球拍小程序:打破拥有束缚,尽享运动乐趣
市场前景: 随着健身和运动的流行趋势,越来越多的人加入了各种体育项目。然而,拥有球拍作为体育装备的成本较高,对于想要尝试不同运动的人来说,这可能是个阻碍。共享球拍小程序迎合了这一需求,提供了一个经济…...
uniapp 微信小程序 绘制海报,长按图片分享,保存海报
uView UI 2.0 dcloud 插件市场地址 弹窗海报源码 <template><!-- 推荐商品弹窗 --><u-popup :show"haibaoShow" mode"center" round26rpx z-index10076 bgColortransparent safeAreaInsetTop close"goodsclose"><image …...
爬虫异常捕获与处理方法详解
Hey!作为一名专业的爬虫代理供应商,我今天要和大家分享一些关于爬虫异常捕获与处理的方法。在进行爬虫操作时,我们经常会遇到各种异常情况,例如网络连接错误、请求超时、数据解析错误等等。这些异常情况可能会导致程序崩溃或数据丢…...
制作网络课堂学习平台(标签嵌套,后代选择器)
网络课堂学习平台 课程 1 这是课程 1 的描述。 模块 1 这是模块 1 的描述。 查看详情 模块 2 这是模块 2 的描述。 查看详情 课程 2 这是课程 2 的描述。 模块 1 这是块 2 的描述。 查看详情...
基于医疗领域数据微调LLaMA——ChatDoctor模型
文章目录 ChatDoctor简介微调实战下载仓库并进入目录创建conda环境并配置环境(安装相关依赖)下载模型文件微调数据微调过程全量微调基于LoRA的微调基于微调后的模型推理 ChatDoctor简介 CHatDoctor论文: ChatDoctor: A Medical Chat Model F…...
UDP TCP 报文内容
1.UDP 2.TCP 源/目的端口号:表示数据是从哪个进程来,到哪个进程去; 32位序号/32位确认号:后面详细讲;4位TCP报头长度:表示该TCP头部有多少个32位bit(有多少个4字节);所以TCP头部最大长度是15*460 6位标志位: o URG:紧急指针是否有效 ——urgent 紧急的 o ACK:确认号是否有…...
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...
用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...
JS设计模式(4):观察者模式
JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中࿰…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
