JVM - Java内存区域
文章目录
目录
文章目录
运行时数据区域
程序计数器
栈
Java虚拟机栈
本地方法栈
栈帧的组成
局部变量表
操作数栈
帧数据
堆
方法区
直接内存
总结
运行时数据区域
Java虚拟机在执行Java程序的过程中会把它所管理的内存区域划分为若干个不同的数据区域。这些区域有各自的用途,以及创建和销毁时间,有的区域随着虚拟机进程的启动而一直存在,有的区域则是依赖用户线程的启动和结束而创建销毁。根据《Java虚拟机规范》的规定,Java虚拟机所管理的内存将会包括一下几个运行时数据区域。

程序计数器
程序计数器(Program Counter Register) 是一块较小的内存空间, 它可以看作是当前线程所执行的字节码的行号指示器。
在代码执行过程中,程序计数器会记录下一行字节码指令的地址.执行完当前指令之后,虚拟机的执行引擎根据程序计数器执行下一行指令

字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令, 它是程序控制流的指示器,分支循环,跳转,异常处理, 线程恢复等基础功能都需要依赖这个计数器完成。为了线程切换后可以恢复到正确的执行位置,每条线程都有一个独立的程序计数器。
线程切换情况下程序计数器工作流程展示
注: 图中显示的数字非真实地址,为了方便使用偏移量进行代替
图1: 线程A上CPU运行

图二: 等到线程A执行到7位置时,cpu切换到线程B上

图三: 线程B执行一段时间,再次切换,解释器读取PA中的信息,从7为位置开始继续执行

图四: 全部执行完毕!

栈
Java虚拟机栈
与程序计数器一样,Java虚拟机栈(Java Virtual Machine Stack) 也是线程私有的, 它的生命周期与线程相同。虚拟机栈描述的是Java方法执行的线程内存模型: 每个方法被执行的时候,Java虚拟机都会同步创建一个栈帧用于存储局部变量表,操作数栈,动态连接,方法出口等信息。每一个方法被调佣直至执行完毕的过程将对应一个栈帧从入栈到出栈的过程。
下面根据一个简单的Java类来分析一下流程

第一步: main方法入栈

第二步: study方法入栈

第三步: eat() 方法和 sleep() 相继入栈

第四步: 相继出栈 从顶部开始

本地方法栈
本地方法栈(Native Method Stack) 与虚拟机所发挥的作用是非常相似的,其区别只是虚拟机栈为虚拟机执行Java方法,而本地方法栈则是为虚拟机使用到的本地方法服务。
栈帧的组成
Java虚拟机以方法作为基本的执行单元, "栈帧" 则是用于支持虚拟机运行方法调用和方法执行背后的数据结构, 它也是虚拟机运行时数据区中的栈元素。栈帧存储了局部变量表,操作数栈,动态连接和方法返回值地址等信息。

局部变量表
局部变量表(Local Variables Table) 是一组变量值的存储空间, 用于存放方法参数和方法内部定义的局部变量。在Java程序被编译为Class文件时,就在方法的Code属性的max_locals数据项中确定了该方法所需分配的局部变量表的最大容量。

栈帧中的局部变量表是一个数组,数组中每一个位置称之为槽(插槽)、Long和Double类型占用两个槽,其他类型占用一个槽 。

实例方法中的序号为0的位置存放的是This,指的是当前调用方法的对象,运行时会在内存中存放实例对象的地址 。

操作数栈
操作数栈也被称为操作栈, 它是一个后进先出(Last In Frist Out LIFO)栈。同局部变量表一样,操作数栈的最大深度也在编译的时候就被写入到Code属性的max_stacks数据项之中。操作数栈的每一个元素都可以是包括long和double在内的任意Java类型数据。

帧数据
帧数据主要包含动态链接,方法出口,异常表的引用。
动态链接
当前类的字节码指令引用了其他类的属性或者方法时,需要将符号引用(编号)转换成对应的运行时常量池中的内存地址.动态链接就保存了编号到运行时常量池的内存地址的映射关系

方法出口
当一个方法开始执行后,只有两种退出方式。第一种方式是执行引擎遇到任何一个方法返回的字节码指令, 这种退出方式称之为"正常调用完成"。另一种退出方式是在方法执行过程中出现了异常, 并且这个异常没有得到妥善处理,被程序直接抛出, 这种方式称之为 "异常调用完成"。
无论采用何种退出方式,在方法退出之后,都必须返回到最初方法被调用时的位置, 程序才能继续运行,方法返回时可能需要在栈帧中保存一些信息,用来帮助恢复它的上层主调方法的执行状态。一般来说如果是正常退出,主调方法的pc计数器的值就可以作为返回地址。而方法异常退出时,返回地址需要借助异常处理表来进行确定。
异常处理表

堆
对于Java程序来说, Java堆(Java Heap) 是虚拟机所管理的内存中占用空间最大的一块。
Java堆是所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是用来存放Java实例。
堆空间有三个需要关注的值,used,total, max。
used指的是当前已使用的堆内存、total 是Java虚拟机已经分配的可用堆内存、max是Java虚拟机可以分配的最大堆内存。

堆大小配置
要修改堆的大小,可以使用虚拟机参数 –Xmx(max最大值)和-Xms (初始的total)。
语法:-Xmx值 -Xms值
单位:字节(默认,必须是 1024 的倍数)、k或者K(KB)、m或者M(MB)、g或者G(GB)
限制:Xmx必须大于 2 MB,Xms必须大于1MB
-Xms6291456
-Xms6144k
-Xms6m
-Xmx83886080
-Xmx81920k
-Xmx80m
方法区
方法区(Method Area)和堆一样,是各个线程共享的一块数据区域。主要包含三部分: 类的元信息,运行时常量池,字符串常量池。
类的元信息
方法区是用来存储每个类的基本信息(元信息),一般称之为InstanceKlass对象。在类的加载阶段完成。

方法区除了存储类的元信息之外,还存放了运行时常量池。常量池中存放的是字节码中的常量池内容。
字节码文件中通过编号查表的方式找到常量,这种常量池称为静态常量池。当常量池加载到内存中之后,可以通过内存地址快速的定位到常量池中的内容,这种常量池称为运行时常量池。

JDK7及之前的版本将方法区存放在堆区域中的永久代空间,堆的大小由虚拟机参数来控制。 ⚫ JDK8及之后的版本将方法区存放在元空间中,元空间位于操作系统维护的直接内存中,默认情况下只要不 超过操作系统承受的上限,可以一直分配。

字符串常量池
方法区中除了类的元信息、运行时常量池之外,还有一块区域叫字符串常量池(StringTable)。 字符串常量池存储在代码中定义的常量字符串内容。
字符串常量池和运行时常量池的关系

练习题:
第一题:


false
第二题:

intern方法:
String.intern()方法是可以手动将字符串放入字符串常量池中。
第三题:
JDK6版本中intern () 方法会把第一次遇到的字符串实例复制到永久代的字符串常量池中,返回的也是永久代里面这个字符串实例的引用。JVM启动时就会把java加入到常量池中。

JDK7及之后版本中由于字符串常量池在堆上,所以intern () 方法会把第一次遇到的字符串的引 用放入字符串常量池。
直接内存
直接内存(Direct Memory)并不在《Java虚拟机规范》中存在,所以并不属于Java运行时的内存区域。 在 JDK 1.4 中引入了 NIO 机制,使用了直接内存,主要为了解决以下两个问题:
1、Java堆中的对象如果不再使用要回收,回收时会影响对象的创建和使用。
2、IO操作比如读文件,需要先把文件读入直接内存(缓冲区)再把数据复制到Java堆中。 现在直接放入直接内存即可,同时Java堆上维护直接内存的引用,减少了数据复制的开销。写文件也是类似的思路。

总结
以上就是这篇博客的主要内容了,大家多多理解,下一篇博客见!
相关文章:
JVM - Java内存区域
文章目录 目录 文章目录 运行时数据区域 程序计数器 栈 Java虚拟机栈 本地方法栈 栈帧的组成 局部变量表 操作数栈 帧数据 堆 方法区 直接内存 总结 运行时数据区域 Java虚拟机在执行Java程序的过程中会把它所管理的内存区域划分为若干个不同的数据区域。这些区…...
本地电脑交叉编译ffmpeg 到 windows on arm64
本地电脑交叉编译ffmpeg 到 windows on arm64 我这里有编译好的win on arm 的 ffmpeg : https://github.com/wmx-github/ffmpeg-wos-arm64-build 使用 llvm-mingw 工具链 https://github.com/mstorsjo/llvm-mingw/releases 前缀 aarch64-w64-mingw32- 这个库是ubuntu 交叉编译…...
使用 @NotEmpty、@NotBlank、@NotNull 注解进行参数校验
使用 NotEmpty、NotBlank、NotNull 注解进行参数校验 一、前言二、依赖三、使用 NotEmpty、NotBlank、NotNull 注解进行参数校验1. NotNull2. NotEmpty3. NotBlank4. 区别与适用场景 四、实践中的应用五、总结 一、前言 在 Java 开发中,参数校验是确保数据一致性和…...
关于Qt在子线程中使用通讯时发生无法接收数据的情况
在多线程应用中,串口通讯或TCP通讯的场景常常涉及到持续的读写操作,如果子线程处理不当,可能会导致信号阻塞问题。本文将通过串口通讯或TCP通讯为例,详细解释如何在多线程环境中避免信号阻塞,并提供代码示例。 1. 问题…...
HTML:从历史演进到未来创新的网页基石
该论文为AI生成,请勿运用到正式的论文上,以下仅供参考 一、引言 1.1 研究背景 HTML(Hypertext Markup Language)作为网页构建的基础语言,在互联网的发展历程中占据着至关重要的地位。自 1993 年诞生以来,…...
向量的叉积、点积、外积
向量的叉积、点积和外积是向量代数中非常重要的操作,用于描述向量间的关系。它们广泛应用于物理、计算机图形学、几何以及蛋白质结构分析等领域。下面对每个运算进行详细介绍,并通过 PyTorch 示例代码展示其实现。 1. 点积 (Dot Product) 点积是两个向量之间的数量积,结果…...
UNI-APP 溢出隐藏显示省略号
✍经常在项目里面使用到,又没有记住懒得找了,故此写一篇记录一下! CSS单行显示省略号 /* CSS样式 */ .ellipsis {overflow: hidden; /* 隐藏超出的内容 */text-overflow: ellipsis; /* 显示省略号 */white-space: nowrap; /* 不换行 */ } CS…...
SAP学习笔记 - 开发03 - CDSView开发环境搭建,Eclipse中连接SAP,CDSView创建
上一章讲了BTP的账号创建,环境搭建等内容。 SAP学习笔记 - 开发02 - BTP实操流程(账号注册,BTP控制台,BTP集成开发环境搭建)-CSDN博客 本章继续讲SAP开发。 - CDSView 的开发环境(Eclipse)搭建…...
uniapp写的一个年月日时分秒时间选择功能
代码: <template><view><picker mode"multiSelector" :value"multiIndex" :range"multiRange" change"onMultiChange"><view class"picker">当前选择:{{ formattedDateTime }}</vie…...
golang hertz框架入门
两种模式新建项目 1、手动新建项目 2、使用hz工具新建项目 一、手动创建项目,并拉取框架 1、新建项目目录 hertz_demo_w 2、在项目跟目录新建main.go 文件 package mainimport ("context""github.com/cloudwego/hertz/pkg/app""github.…...
Android Home应用程序启动流程
Android系统在启动时安装应用程序的过程,这些应用程序安装好之后,还需要有一个Home应用程序来负责把它们在桌面上展示出来,在Android系统中,这个默认的Home应用程序就是Launcher了,本文将详细分析Launcher应用程序的启…...
C++笔试强训12、13、14
文章目录 笔试强训12一、选择题1-5题6-10题 二、编程题题目一题目二 笔试强训13一、选择题1-5题6-10题 二、编程题题目一题目二 笔试强训14一、选择题1-5题6-10题 二、编程题题目一题目二 笔试强训12 一、选择题 1-5题 引用:是一个别名,与其被引用的实…...
Excel和Word日常使用记录:
Excel使用总结 表格颜色填充: 合并单元格: 选中你要合并的单元格区域。 按下快捷键 Alt H,然后松开这些键。 再按下 M,接着按 C。 这个组合键执行的操作是:Alt H:打开“主页”选项卡。 M:选…...
用Git把本地仓库上传到远程仓库
用Git把本地仓库上传到远程仓库 GitHub创建远程仓库 在创建新仓库界面里输入你的仓库名后点击Create repository就好了。 创建本地项目 当你已经有一个项目后在命令行输入如下指令即可 git init git commit -m "first commit" git branch -M main git remote a…...
OneHotEncoder一个不太合理的地方
OneHotEncoder,在Xtrain上fit,在Xtest上transform 如果遇到某个值出现在Xtest,而没有在Xtrain出现过时,会抛出如下错误: OneHotEncoder Found unknown categories [xxx] in column xx during transform OneHotEncoder …...
如何修复软件中的BUG
笔者上一篇博文《如何开发出一款优秀的软件》主要讲了如何开发一款优秀的软件及相应的必要条件。但对一个已上线,已经成型的产品,该如何解决存在的bug呢?这是本文要阐述的内容。 在这里,首先说一下bug的种类及bug严重程度分类&…...
分享一个基于微信小程序的医院挂号就诊一体化平台uniapp医院辅助挂号应用小程序设计(源码、调试、LW、开题、PPT)
💕💕作者:计算机源码社 💕💕个人简介:本人 八年开发经验,擅长Java、Python、PHP、.NET、Node.js、Android、微信小程序、爬虫、大数据、机器学习等,大家有这一块的问题可以一起交流&…...
HTML生日蛋糕
目录 写在前面 完整代码 代码分析 系列文章 写在最后 写在前面 HTML实现的生日蛋糕来喽,小编亲测,发给好友可以直接打开哦。在代码的第183行可以写下对朋友的祝福,快拿去送给你的好朋友吧! 完整代码 <!DOCTYPE html>…...
【软件逆向】第27课,软件逆向安全工程师之(二)寄存器寻址,每天5分钟学习逆向吧!
寄存器寻址是汇编语言中的一种寻址方式,在这种方式中,操作数位于CPU的寄存器中。寄存器是CPU内部的高速存储位置,用于快速访问数据。以下是关于寄存器寻址的详细信息: 寄存器寻址的特点: 操作数在寄存器中࿱…...
前缀和 — 利用前缀信息解决子数组问题
【前缀和的核心思想是预先处理数组来快速计算任意子数组的和,基本上用于数组和序列问题。】 前缀和算法具体步骤 构造前缀和数组: 给定一个数组nums,其前缀和数组prex定义为prex[i]表示为数组nums从起始位置到第i个位置的元素累加和。构建前…...
Radiant Player媒体键集成:揭秘硬件控制背后的技术
Radiant Player媒体键集成:揭秘硬件控制背后的技术 【免费下载链接】radiant-player-mac :notes: Turn Google Play Music into a separate, beautiful application that integrates with your Mac. 项目地址: https://gitcode.com/gh_mirrors/ra/radiant-player-…...
Nginx 高可用、负载均衡与 HTTPS 配置实战(一)
Nginx作为当下最主流的开源反向代理与Web服务器,凭借轻量、高性能、高并发的特性,成为企业级服务入口的首选方案。在生产环境中,单节点Nginx存在单点故障风险,并发请求过高会导致服务卡顿,同时HTTP明文传输存在数据泄露…...
交付前批量人脸脱敏自动模糊的一点记录
客户给了一批线下沙龙现场图,两百三十张上下,要用于对外案例页,合同里写了人脸需做不可辨认处理。手工框选不现实,我这次用【批量图片面部识别自动模糊工具】走完整交付链,只记和排期、验收相关的点。输入支持拖文件夹…...
Factory IO + S7-PLCSIM V18 仿真避坑指南:如何解决传感器信号丢失和传送带卡料问题
Factory IO与S7-PLCSIM V18工业仿真实战:传感器优化与传送带故障排除指南 在工业自动化仿真领域,Factory IO与西门子S7-PLCSIM V18的组合已经成为工程师验证智能工厂逻辑的高效工具链。这套解决方案能够完整模拟从物料加工到仓储的完整产线,但…...
别再手动记数据了!组态王Kingview 7.5 SP6搭配Access数据库,实现工业数据自动存储与查询
工业数据自动化管理实战:组态王与Access的高效联动方案 在工业现场,数据采集与记录是保障生产稳定运行的基础环节。传统的手工记录方式不仅效率低下,还容易因人为因素导致数据错漏。我曾在一家化工厂亲眼目睹操作员因记录笔误导致整批生产参数…...
关于sms,voip路由以及smpp
SMS 和 VoIP 路由是国际通讯行业核心技术,用于高效传递短信和语音通话。SMPP 协议则是 SMS 传输的关键标准,帮助运营商和企业实现全球消息互联。SMS 基础知识SMS(Short Message Service,短消息服务)是手机最常见的文本…...
Fluent后处理效率翻倍:用View功能建立你的专属仿真报告视角库
Fluent后处理效率翻倍:用View功能建立你的专属仿真报告视角库 在仿真工程师的日常工作中,最耗时的往往不是计算本身,而是后处理阶段——反复调整视角、截图、标注、排版,只为生成一份清晰直观的报告。我曾参与过一个散热器优化项目…...
用STM32F4做个PWM信号发生器:按键调参+OLED显示,示波器实测验证
用STM32F4打造高精度PWM信号发生器:从原理到实战 在电子开发与测试中,PWM信号发生器是不可或缺的工具。专业信号源价格昂贵,而基于STM32F4的开发板却能以极低成本实现类似功能。本文将带你从零构建一个带OLED显示和按键控制的PWM信号发生器&…...
用QT5的QTcpSocket做一个TCP调试助手:连接单片机/服务器测试数据收发
用QT5打造专业级TCP调试助手:从基础通信到工业级工具开发 在嵌入式开发和物联网项目中,TCP通信调试是每个工程师都会遇到的常规需求。无论是与STM32单片机通信,还是测试PLC设备的网络功能,亦或是验证云服务器的数据接口࿰…...
从概念到工具:实战构建基于clawhub skill的个人技能管理体系
最近在整理自己的技能树时,发现需要一个能直观管理个人技术栈的工具。尝试用clawhub skill框架搭建了一套解决方案,配合InsCode(快马)平台的快速部署能力,三天就做出了可实际使用的技能看板。记录下关键实现思路,或许对同样想系统…...
