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个位置的元素累加和。构建前…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
