【深入理解JVM】内存模型

news2024/10/7 6:44:21

目录

运行时数据区域

程序计数器

Java虚拟机栈

本地方法栈

Java堆

方法区

运行时常量池

直接内存

虚拟机对象探秘

对象的创建

对象的内存布局


运行时数据区域

程序计数器

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

处理器的一个逻辑核同一时间只会执行一个线程的字节码指令,而java虚拟机的多线程是通过线程轮流切换、分配处理器的执行时间来实现。为了多线程切换后能够恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各个线程之间计数器互不影响,独立存储,属于线程私有的内存。

如果线程正在执行的是一个java方法,计数器记录的是正在执行的字节码指令的地址;如果执行的是native方法,这个计数器的值为空,此内存是唯一一个没有OOM的区域

Java虚拟机栈

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

  • 局部变量表

局部变量表存放了编译期可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用和returnAddress类型(指向了一条字节码指令的地址)

这些数据类型在局部变量表中的存储空间以局部变量槽(Slot)为单位的数组来表示,long和double的数据会占用两个变量槽,其余的数据类型只占用一个。局部变量表所需要的内存空间在编译期完成分配,当进入一个方法时,这个方法需要在栈帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小(大小指的是变量槽的数量,一个变量槽32个比特、64个比特或者更多完全由具体的虚拟机实现)。

线程请求的栈深度大于虚拟机允许的深度,抛出StackOverflowError;如果虚拟机栈容量可以动态扩展,当扩展时无法申请到足够的内存抛出OOM

  • 操作数栈

与局部变量表一样,均以Slot为单位的数组。不过局部变量表用的是索引,操作数栈是弹栈/压栈来访问。操作数栈可理解为java虚拟机栈中的一个用于计算的临时数据存储区。

存储的数据与局部变量表一致int、long、float、double、reference、returnType,操作数栈中byte、short、char压栈前(bipush)会被转为int。数据运算的地方,大多数指令都在操作数栈弹栈运算,然后结果压栈。

java虚拟机栈是方法调用和执行的空间,每个方法会封装成一个栈帧压入栈中。其中里面的操作数栈用于进行运算,当前线程只有当前执行的方法才会在栈帧的操作数栈中调用指令(可见java虚拟机栈的指令主要取于操作数栈)

下面一段字节码表述了局部变量表和操作数栈的关系:

本地方法栈

和java虚拟机栈类似也是线程私有的,区别就是虚拟机栈是为虚拟机执行java方法(字节码)服务,而本地方法栈是为虚拟机使用本地方法(native)服务

Java堆

gc回收的主要区域,所有线程共享。从内存分配的角度,可以划分出多个线程私有的分配缓冲区(TLAB),以提升对象分配时的效率。-Xmx和-Xms指定堆的大小。内存不足分配实例时OOM

方法区

线程共享的内存区域。用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码缓存等数据。方法区无法满足新的内存分配需求时,OOM

运行时常量池

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

运行时常量池的一个重要特性是具备动态性,运行期间也可以将新的常量放入池中,用的比较多的就是String.intern()方法。

当常量无法在申请时OOM

直接内存

NIO类引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O方式,可以使用native函数直接分配堆外内存,然后通过一个存储在Java堆里面的DirectByteBuffer对象引用这块内存进行操作。能在一些场景中显著提升性能,避免了在Java堆和Native堆中来回复制数据。

受到本机总内存的限制,内存不足OOM

虚拟机对象探秘

对象的创建

new关键字 -> 检查指令的参数在常量池中定位到一个类的符号引用 -> 类是否被加载、解析、初始化 -> 为对象分配内存(对象所需内存在类加载完成后可完全确定)-> 将分配的内存空间(不包括对象头)初始化为零值(保证了java代码中可以不赋值直接使用)-> 设置对象头(类的元数据信息、对象哈希码、gc分代年龄等)-> 执行构造函数init<>()方法

分配内存方式有指针碰撞、空闲列表,serial、ParNew等待压缩整理过程的收集器,使用指针碰撞,CMS这种基于标记清楚的使用空闲列表。同时多线程创建对象为了保证线程安全:CAS配上失败重试的方式保证更新操作的原子性;为每个线程预分配一小块内存TLAB,当线程的TLAB使用完了,分配新的缓存区才需要同步锁定。

对象的内存布局

对象头

  • Mark Word

比如 hash码,对象所属的年代,对象锁,锁状态标志,偏向锁(线程)ID,偏向时间,数组长度(数组对象)等。Java对象头一般占有2个机器码(64位虚拟机中,1个机器码是8个字节,也就是64bit),但是 如果对象是数组类型,则需要3个机器码,因为JVM虚拟机可以通过Java对象的元数据信息确定Java对象的大小,但是无法从数组的元数据来确认数组的大小,所以用一块来记录数组长度

  • 指向类的指针

大小也通常为32bit,它主要指向类的数据,也就是指向方法区中的位置。

  • 数组长度

只有数组对象才有,在32位或者64位JVM中,长度都是32bit

实例数据

对象真正存储的有效信息,我们在程序代码里定义的各种类型的字段内容,无论是从父类中继承下来的,还是在子类中定义的字段都必须记录起来。

对齐填充

由于虚拟机要求 对象起始地址必须是8字节的整数倍。填充数据不是必须存在的,仅仅是为了字节对齐。原因是为了寻址最优,64位机器正好8个字节;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/154425.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C#开发的资源文件程序(可国际化) - 开源研究系列文章

上次将小软件的线程池描述了&#xff0c;也将插件程序描述了&#xff0c;这次就将里面的资源文件相关的内容进行下记录&#xff0c;这里能够让程序做成国际化的形式(即多语言程序)&#xff0c;主要就是通过这个资源文件的方式进行的处理。下面将对这个资源文件的定义进行描述&a…

多线程之waitnotify

目录&#xff1a; 前言 1.wait()方法 2 notify()方法 3.wait & notify的代码示例&#xff1a; 4.关于notifyAll()方法 前言 线程最大的问题就是抢占式执行&#xff0c;随机调度。虽然线程在操作系统内核里的调度是随机的&#xff0c;但是可以通过一些办法来控制线程…

带你了解SVG标签

✍️ 作者简介: 前端新手学习中。 &#x1f482; 作者主页: 在主页中查看更多前端教学&#xff0c;可接大学生前端作业单。 &#x1f393; 专栏分享&#xff1a;css重难点教学 Node.js教学 从头开始学习 ajax学习 js学习 目录初始SVG矩形&#xff0c;圆形和椭圆型 矩形 圆…

云安全(云安全数据中心、WAF、DDOS)

安全 安全威胁 可用性 安全威胁&#xff1a;大规模分布式拒绝服务攻击(DDoS)、僵尸网络(Botnet) 影响&#xff1a;网站业务不可用 完整性 安全威胁&#xff1a;网站入侵、服务器口令暴力破解 影响&#xff1a;网站页面被篡改和植入后门 保密性 安全威胁&#xff1a;网站后门…

二、Groovy入门

文章目录二、Groovy入门2.1 Groovy 简介2.2 Groovy 安装[非必须]2.3 IDEA创建 Groovy 项目2.4 Groovy 基本语法2.4.1 案例 1:基本注意点2.4.2 案例 2:引号说明2.4.3 案例 3:三个语句结构2.4.4 案例 4:类型及权限修饰符2.4.5 案例 5:集合操作2.4.6 案例 6:类导入2.4.7 案例 7:异…

MySQL是怎么保证主备一致的?

在前面的文章中,我不止一次地和你提到了 binlog,大家知道 binlog 可以用来归档,也可以用来做主备同步,但它的内容是什么样的呢?为什么备库执行了 binlog 就可以跟主库保持一致了呢?今天我就正式地和你介绍一下它。 毫不夸张地说,MySQL 能够成为现下最流行的开源数据库,…

pytorch torchvision.ops.roi_align

pytorch的torchvision.ops.roi_align这个算子真的是坑我好多天啊&#xff01;害我连续加班半个月&#xff01;二阶段目标检测后面用roi_align来提取特征。 接口官方说明&#xff1a;https://pytorch.org/vision/stable/generated/torchvision.ops.roi_align.html?highlightroi…

React Devtools 使用技巧

首先在扩展迷中搜索下载该扩展&#xff0c;引入到 Chrome 的扩展程序中。 当我们添加扩展到Chrome中&#xff0c;就会在浏览器中看到 React Devtools 的 Icon&#xff0c;同时通过该扩展我们就可以知道当前打开的网站是开发环境的网站还是生产环境&#xff0c;React Devtools …

Mysql 安装 ubutu20.04

Mysql 安装 1&#xff1a;sudo apt-get autoremove --purge mysql* 2&#xff1a;sudo apt-get install mysql-server 3&#xff1a;sudo apt --fix-broken install -y 4&#xff1a;sudo apt-get install mysql-server 5&#xff1a; service mysql status 5&#xff1a;sudo…

C++STL-stackqueuepriority_queue介绍

文章目录1. 容器适配器1.1 什么是适配器1.2 STL标准库中stack和queue的底层结构2. stack的介绍和使用2.1 stack的介绍2.2 stack的使用3. queue的介绍和使用3.1 queue的介绍3.2 queue的使用4. priority_queue的介绍和使用4.1 priority_queue的介绍4.2 priority_queue的使用1. 容…

年度征文 | 回顾2022,展望2023

目录 一、前言 二、回顾2022 三、展望2023 个人主页: ζ小菜鸡大家好我是ζ小菜鸡&#xff0c;感谢大家一直的支持。岁末年初&#xff0c;让我们一起回顾2022展望2023。一、前言 时光荏苒&#xff0c;岁月如梭&#xff0c;2022 已和我们再见&#xff0c;2023 正向我们走来。…

云原生周刊 | 在 Grafana 中显示 K8s Service 之间的依赖关系

开源项目推荐 Caretta 这个项目可以在 Grafana 监控面板中显示 K8s Service 之间的依赖关系。底层使用的是 eBPF&#xff0c;对应用无侵入。 busuanzi 这是一个基于 Golang Redis 的简易访问量统计系统&#xff0c;可以用来替代不蒜子。 vim-online-editor 这是一个在线版…

一文读懂 Kubernetes 存储设计

在 Docker 的设计中&#xff0c;容器内的文件是临时存放的&#xff0c;并且随着容器的删除&#xff0c;容器内部的数据也会一同被清空。不过&#xff0c;我们可以通过在 docker run 启动容器时&#xff0c;使用 --volume/-v 参数来指定挂载卷&#xff0c;这样就能够将容器内部的…

企业级数据中台构建方法和指导

目录1. 数据中台的概念2. 数据中台适合企业2.1 企业构建数据中台面临的问题2.2 企业构建数据中台解决问题的方法2.3 什么样的企业适合构建数据中台3. 如何建设数据中台3.1 方法论3.1.1 OneData3.1.2 OneService3.2 技术3.3 组织4. 数据中台实现&#xff1a;指标管理5. 数据中台…

高速缓存伪共享(false sharing)

0. CPU缓存 根据摩尔定律&#xff1a;芯片中的晶体管数量每隔18个月就会翻一番。导致CPU的性能和处理速度变得越来越快&#xff0c;而提升CPU的运行速度比提升内存的运行速度要容易和便宜的多&#xff0c;所以就导致了CPU与内存之间的速度差距越来越大。 为了弥补CPU与内存之间…

错失搭档张云雷,杨九郎和郭冬临一起演小品

熟悉相声的人都知道&#xff0c;这个传统的曲艺行业&#xff0c;一般是由捧哏和逗哏组成&#xff0c;两个人相辅相成缺一不可。就拿德云社的相声演员来说&#xff0c;也产生了很多对优秀演员&#xff0c;比如说郭德纲和于谦&#xff0c;比如说岳云鹏和孙越等等。 除了这两对相声…

微信开放平台之小程序获取用户信息

说实话&#xff0c;微信开放平台的文档真的是狗屎一般的存在&#xff0c;维护不及时&#xff0c;混乱&#xff0c;每隔一段时间更新一次授权接口&#xff01;着实让开发者想口吐芬芳了&#xff01;文档内跳来跳去&#xff0c;找不到一个完整的链路&#xff01;维护好几套接口文…

_Linux多线程-线程控制篇

文章目录1. POSIX线程库2. 创建线程3. 线程ID及进程地址空间布局4. 线程等待5. 线程终止pthread_ exitpthread_ cancel6. 分离线程7. 总结1. POSIX线程库 与线程有关的函数构成了一个完整的系列&#xff0c;绝大多数函数的名字都是以“pthread_”打头的要使用这些函数库&#…

三角函数在编程中的实际运用—永劫无间脚本

三角函数在编程中的实际运用—永劫无间脚本前言需求思路代码■ 转义码■ 源码具体讲解三角函数计算相对移动求余跳过不需要的位置成品最后前言 义务教育下&#xff0c;年轻人从初中就开始学三角函数却半辈子也没用上&#xff0c;除了特殊行业&#xff0c;做开发的可能也就大学…

Nginx web服务器入门及其在Linux中的搭建

目录 ​编辑 一、Nginx基本概述 1.介绍 2.优点 3.应用场景 &#xff08;1&#xff09;负载均衡 &#xff08;2&#xff09;代理缓存 &#xff08;3&#xff09;静态资源 &#xff08;4&#xff09;安全应用场景 4.Nginx的组成 &#xff08;1&#xff09;Nginx二进制…