JVM 系列:JVM 内存结构深度解析

你点赞了吗?你关注了吗?每天分享干货好文。

高并发解决方案与架构设计。

海量数据存储和性能优化。

通用框架/组件设计与封装。

如何设计合适的技术架构?

如何成功转型架构设计与技术管理?

在竞争激烈的大环境下,只有不断提升核心竞争力才能立于不败之地。

留言【我要晋级】,一对一指导,带你晋级。

一、JVM 内存结构总览

JVM 内存结构是 Java 程序运行的基石,定义了数据在虚拟机中的存储与访问规则。其核心分为 ‌线程私有区域(线程隔离)‌ 和 ‌线程共享区域‌,具体划分如下图

线程私有区域(线程隔离)‌ :程序计数器、虚拟机栈、本地方法栈

线程共享区域‌:堆、方法区

从类型上分,也可以大致分为:堆、栈。堆是存储单元,主要作用是存储数据的。栈是运行单元,主要作用是解决程序如何运行。一个为线程执行服务,一个为全局数据存储。

二、程序计数器(Program Counter Register)

程序计数器是线程私有的内存区域,用于存储当前线程执行的字节码指令地址。如果线程正在执行本地方法,程序计数器的值为空(Undefined)。

程序计数器是一块较小的内存空间,也是运行速度最快的存储区域。它可以看作是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里(仅是概念模型,各种虚拟机可能会通过一些更高效的方式去实现),字节码码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成

说人话就是:用于存储当前线程执行的字节码指令地址。

由于 Java 虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(对于多核处理器来说就是一个内核)都只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要一个独立的程序计数器,各条线程之间计数器互不影响,独立存储,我们称这类的内存区域为“线程私有”的内存。

如果线程正在执行的是一个 Java 方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行本地方法(Native),这个计数器值则为空(Undefined)。

此内存区域是唯一一个在Java虚拟机规范中没有任何 OutOfMemoryError 情况的区域。

生命周期:程序计数器的生命周期与线程的生命周期一致。

三、虚拟机栈(VM Stack)

虚拟机栈是线程私有的内存区域,由多个栈帧(Stack Frame)构成,在当前线程中,每调用一个方法,都会有一个对应的栈帧进行入栈,用于存储方法调用的局部变量、操作数栈、动态链接、方法出口等信息。当方法结束时,对应的方法的栈帧就会进行出栈。每个线程在创建时都会分配一个栈。

虚拟机栈包含以下几个部分:

局部变量表:用于存储方法参数和局部变量。

操作数栈:用于存储方法执行过程中的操作数。

动态链接:指向运行时常量池中该方法的引用。

方法出口:记录方法返回的地址。

一些附加信息

生命周期:栈的生命周期与线程的生命周期一致。线程启动时创建栈,线程结束时销毁栈。

设置大小:Java 虚拟机规范允许 虚拟机栈的大小是动态的或者是固定的。可以通过参数-Xss来设置线程的最大栈空间,栈的大小直接决定了函数调用的最大可达深度。

当栈达到最大栈空间限制时,又要进行新的方法调用(入栈操作)时,就会抛出 StackOverflowError 异常。

当线程创建的时候,没有足够的空间穿件对应的虚拟机栈时,就会抛出 OutOfMemoryError 异常。

四、本地方法栈(Native Method Stack)

本地方法栈与栈类似,但它是为本地方法(Native Method)服务的。本地方法是用其他语言(如 C、C++)编写的方法。

生命周期:本地方法栈的生命周期与线程的生命周期一致。

常见问题也与虚拟机栈类似。

五、堆(Heap)

堆是 JVM 中最大的一块内存区域,是存储 Java 程序中绝大多数的对象实例。是所有线程共享堆内存。Java 虚拟机规范中,把堆进行了划分,主要分为:新生代、老年代、元空间(JDK 8 之前是永久代)。

生命周期:堆的生命周期与 JVM 的生命周期一致。JVM 启动时创建堆,JVM 关闭时销毁堆。

设置大小:堆的大小可以通过-Xmx(最大堆)、-Xms(初始堆)控制大小。

新生代(Young Generation)

新创建的对象一般首先分配在新生代中,除非对象过大直接进入老年代。新生代又分为 Eden 区和两个 Survivor 区(通常称为 S0 和 S1)。默认占比是 8 : 1 : 1。正常情况下两个 Survivor 区总有一个是空的。后面聊垃圾回收的时候,我们可以细聊。

当 Eden 区满了,会执行 ‌Minor GC‌,将 Eden 区和当前使用的 Survivor 区的幸存对象移动到空的 Survivor 区中。每经历过一次 ‌Minor GC‌,幸存的对象其年龄计数器 +1,达到阈值(默认15)后会晋升至老年代。

老年代(Old Generation)

老年代通过是内存满时执行垃圾回收,如果回收后依旧没有空出空间,新对象无位置存储,则会抛出 OutOfMemoryError 异常。

元空间(Metaspace)

存储类信息、常量池等。

元空间可以通过-XX:MetaspaceSize(初始大小)、-XX:MaxMetaspaceSize(最大限制)‌控制大小。

不论是 JDK 8 之前的永久代,还是 JDK 8 之后的元空间,其实都可以理解为虚拟机规范中方法区的具体实现。

虽然虚拟机规范把方法区描述为堆的一部分,但是它其实有一个别名 Non-Heap(非堆)。具体的我们详见方法区部分。

六、方法区(Method Area)

方法区是虚拟机规范中定义的一个概念,是所有线程共享的内存区域,主要用于存储类信息、常量、静态变量、即时编译器编译后的代码等数据。然后虚拟机规范中并没有规定如何去实现它,不同的虚拟机厂商有不同的实现。

永久代(PermGen)则是 Hotspot 虚拟机特有的一个概念,在 JDK 8 中,又被改为元空间。

其实永久代合元空间都可以理解为是方法区的具体实现。

生命周期:方法区的生命周期与 JVM 的生命周期一致。当 JVM 启动时,方法区被创建;当 JVM 关闭时,方法区被销毁。

方法区主要包含以下几个部分:

类信息:包括类的名称、访问修饰符、字段描述、方法描述等。

运行时常量池:用于存储编译期生成的各种字面量和符号引用。

静态变量:类级别的静态变量。

即时编译器编译后的代码:JIT(Just-In-Time)编译器将热点代码编译为本地机器代码后存储在此。

设置大小:JDK 8 之后,可以使用参数 -XX:MetaspaceSize-XX:MaxMetaspaceSize 指定。

方法区的大小决定了JVM 可以加载多少个 Class,如果加载的 Class 过多,则会抛出 OutOfMemoryError异常。如果不指定大小的情况下,默认虚拟机会耗尽系统所有的可用内存。

-XX:MetaspaceSize :设置初始的元空间大小。64 位 JVM默认的 -XX:MetaspaceSize=2075MB,这是初始大小,当达到这个大小后,将会触发 Full GC(Stop the world),卸载无用的 Class(Class 对应的ClassLoader 不再存活),并重置元空间大小(不超过 -XX:MaxMetaspaceSize),重置的值取决于 Full GC 后释放了多少的元空间。

如果初始化-XX:MetaspaceSize过低,元空间的大小会发生多次调整,为了避免因为元空间初始大小过小导致的频繁 Full GC,建议将 -XX:MetaspaceSize 设置为一个相对较高的值。

架构设计之道在于在不同的场景采用合适的架构设计,架构设计没有完美,只有合适。

在代码的路上,我们一起砥砺前行。用代码改变世界!

如果有其它问题,欢迎评论区沟通。

感谢观看,如果觉得对您有用,还请动动您那发财的手指头,点赞、转发、在看、收藏。

高并发解决方案与架构设计。

海量数据存储和性能优化。

通用框架/组件设计与封装。

如何设计合适的技术架构?

如何成功转型架构设计与技术管理?

在竞争激烈的大环境下,只有不断提升核心竞争力才能立于不败之地。

留言【我要晋级】,一对一指导,带你晋级。

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

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

相关文章

手机上的APN是什么,该怎么设置

网上说改个APN就可以让网速快几倍,那到底APN是个什么东西,真的能让网速快几倍吗? APN的作用 网络连接基础:APN(接入点名称)是手机连接移动网络的“桥梁”,负责识别运营商网络类型(…

微服务治理与可观测性

服务注册与发现 核心功能 服务实例动态变化:实例可能因扩缩容、故障或迁移导致IP变动。服务依赖解耦:调用方无需硬编码服务地址,降低耦合度。负载均衡:自动选择健康实例,提升系统可用性。 核心组件 服务注册中心&am…

嵌入式linux系统中内存管理的方法与实现

第一:linux内核管理详解图形 第二:Linux内存管理详细分析 深入剖析Linux内核内存管理 作为嵌入式系统开发者,理解Linux内核的内存管理对于开发高效、稳定的系统至关重要。在这篇文章中,我们将详细解析Linux内核如何划分物理内存和虚拟内存,页表、MMU(内存管理单元)与TL…

【dataframe显示不全问题】打开一个行列超多的excel转成df之后行列显示不全

出现问题如下图: 解决方案~ display.width解决列显示不全 pd.set_option(display.max_columns,1000) pd.set_option(display.width, 1000) pd.set_option(display.max_colwidth,1000) pd.set_option(display.max_rows,1000)

Linux——Shell编程之正则表达式与文本处理器(笔记)

目录 基础正则表达式 1:基础正则表达式示例 (4)查找任意一个字符“.”与重新字符“*” (5)查找连续字符范围“{ }” 文本处理器 一、sed工具 二、awk工具 (1)按行输出文本 (2&#xff0…

OpenHarmony系统-源码下载,环境搭建,编译,烧录,调试

获取源码 以OpenHarmony5.0.3为例 repo init -u https://gitee.com/openharmony/manifest -b OpenHarmony-5.0.3-Release --no-repo-verify repo sync -c repo forall -c git lfs pull搭建环境 安装必要的工具和命令 apt-get install -y apt-utils binutils bison flex bc …

Vue3 本地打包启动白屏解决思路!! !

“为什么我访问 http://127.0.0.1:5501/index.html 白屏,删了 index.html 再访问 / 就又活过来了?” —— 你的项目与 SPA 路由的“宫斗大戏” 一、问题复现 场景 本地通过 VSCode Live Server(或其他静态服务器)启动了打包后的 V…

数字人(2):数字人技术全景透视(2025演进版)

随着人工智能技术的迅猛发展,数字人技术发展也是一日千里。站在当下,着眼未来,我们一起在回眸透视过去的基础上,一起共同眺望数字人技术的未来。 一、数字人技术体系重构 我们可以用三维定义对数字人技术进行框架重构 维度 技术内涵 典型特征 物理层 人体数字化建模技术 …

小刚说C语言刷题——1035 判断成绩等级

1.题目描述 输入某学生成绩,如果 86分以上(包括 86分)则输出 VERY GOOD ,如果在 60到 85之间的则输出 GOOD (包括 60和 85),小于 60 的则输出 BAD。 输入 输入只有一行,包括 1个整数。 输出 输出只有一行&#xf…

React-在使用map循环数组渲染列表时须指定唯一且稳定值的key

在渲染列表的时候,我们须给组件或者元素分配一个唯一值的key, key是一个特殊的属性,不会最终加在元素上面,也无法通过props.key来获取,仅在react内部使用。react中的key本质是服务于diff算法, 它的默认值是null, 在diff算法过程中…

Zookeeper的通知机制是什么?

大家好,我是锋哥。今天分享关于【Zookeeper的通知机制是什么?】面试题。希望对大家有帮助; Zookeeper的通知机制是什么? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Zookeeper 的通知机制是其核心特性之一&#xf…

【LangChain实战】构建下一代智能问答系统:从RAG架构到生产级优化

打破传统问答系统的次元壁 当ChatGPT在2022年掀起AI革命时,开发者们很快发现一个残酷现实:通用大模型在专业领域的表现如同拿着地图的盲人,既无法理解企业私有数据,也无法保证事实准确性。这催生了RAG(检索增强生成&a…

UDS中功能寻址可以请求多帧数据嘛?当ECU响应首帧后,诊断仪是通过物理寻址发送流控帧嘛?

文章目录 1. 前言📢1.1 功能寻址是否支持请求多帧数据?1.2 ECU发送首帧(FF)后,诊断仪如何发送流控帧(FC)?1.3 协议依据(ISO 14229-1)1.4 实际应用注意事项总结1. 前言📢 在UDS(Unified Diagnostic Services)协议中,功能寻址与物理寻址的使用规则以及多帧数据传…

PHP异常处理__Throwable

在 PHP 里,Throwable 是一个极为关键的接口,自 PHP 7 起被引入。它为错误和异常处理构建了一个统一的框架。下面会详细介绍 Throwable 的相关内容。 1. 基本概念 Throwable 是 Exception 和 Error 的父接口。在 PHP 7 之前,异常&#xff08…

无需训练的具身导航探索!TRAVEL:零样本视觉语言导航中的检索与对齐

作者: Navid Rajabi, Jana Kosecka 单位:乔治梅森大学计算机科学系 论文标题:TRAVEL: Training-Free Retrieval and Alignment for Vision-and-Language Navigation 论文链接:https://arxiv.org/pdf/2502.07306 主要贡献 提出…

Vue3+Vite+TypeScript+Element Plus开发-22.客制Table组件

系列文档目录 Vue3ViteTypeScript安装 Element Plus安装与配置 主页设计与router配置 静态菜单设计 Pinia引入 Header响应式菜单缩展 Mockjs引用与Axios封装 登录设计 登录成功跳转主页 多用户动态加载菜单 Pinia持久化 动态路由 -动态增加路由 动态路由-动态删除…

Java读取JSON文件并将其中元素转为JSON对象输出

🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Java读取JSON文件并将其中元素转为JSON对象输…

Spring Boot自动配置原理深度解析:从条件注解到spring.factories

大家好!今天我们来深入探讨Spring Boot最神奇的特性之一——自动配置(Auto-configuration)。这个功能让Spring Boot如此受欢迎,因为它大大简化了我们的开发工作。让我们一起来揭开它的神秘面纱吧!👀 🌟 什么是自动配置…

【ELF2学习板】利用OpenMP采用多核并行技术提升FFTW的性能

目录 引言 OpenMP简介 编译OpenMP支持的FFTW库 部署与测试 测试程序 程序部署 测试结果 结语 引言 在前面已经介绍了在ELF2开发板上运行FFTW计算FFT。今天尝试利用RK3588的多核运算能力来加速FFT运算。FFTW利用多核能力可以考虑使用多线程或者OpenMP。今天介绍一下Ope…

2000-2017年各省城市天然气供气总量数据

2000-2017年各省城市天然气供气总量数据 1、时间:2000-2017年 2、来源:国家统计局、能源年鉴 3、指标:行政区划代码、城市、年份、城市天然气供气总量 4、范围:31省 5、指标说明:城市天然气供气总量是指在一定时间…