JVM的组成--运行时数据区

JVM的组成

1、类加载器(ClassLoader)

类加载器负责将字节码文件从文件系统中加载到JVM中,分为:加载、链接(验证、准备、解析)、和初始化三个阶段

2、运行时数据区

运行时数据区包括:程序计数器、虚拟机栈、堆、本地方法栈、方法区(元空间)

3、执行引擎

执行引擎负责将字节码(.class)解释或编译为机器码并执行。包括:解释器、即时编译器(JIT)、垃圾回收器

4、本地方法接口

本地方法接口提供JVM与本地方法库(如C/C++库)的交互能力,使得Java程序可以调用本地方法

一 程序计数器

程序计数器 :是线程私有的,内部保存字节码(.class文件)的行号。用于记录正在执行的字节码指令的地址

由于是线程私有的,所以不会有线程安全问题

使用javap -v xx.class 可以打印堆栈大小,局部变量的数量和方法的参数

可以看到如下图:

class的每一行都被解析成更多的执行命令(指令),每一行前面都有一个行号(地址),记录程序已经执行到哪一行

有什么用呢?比如:当线程1 执行到第10行,这个时候如果CPU被线程2抢走了

等到下次执行的时候,线程1不必从头执行,直接从第10行继续执行

这就是程序计数器的作用

二 堆

堆是线程共享的区域,主要用来保存对象实例,数组等大的、或者生命周期长的对象,当那个堆中没有内存空间可分配给实例,也无法再扩展时,则抛出OutOfMemoryError异常

既然是线程共享的区域,就说明可能有线程安全的问题

如图所示,堆分为两块区域

1、年轻代:分为Eden区,两个大小严格相同的Survivor区S0和S1

根据GC的策略,在经过几次垃圾回收后,仍然存活于Survivor区的对象将被移动到老年代

2、老年代:主要保存一些声明周期长的对象,一般是一些老的对象

三 虚拟机栈

Java Virtual machine Stacks(Java虚拟机栈):

1、是每个线程运行时所需的内存,称为虚拟机栈,先进后出,一般会用来存储局部变量、方法调用

保存局部变量表、操作数栈、动态链接和方法出口等信息

2、如果有多个线程,则会创建多个虚拟机栈,因此只要是在虚拟机栈内,则是线程安全的

每个栈由多个栈帧(frame)组成,对应着每次方法调用时所占用的内存,一个方法一个栈帧

当方法调用方法时,就会在栈中,出现一条栈帧链

3、每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法

如图:方法1调用方法2,方法2调用方法3

则方法1的栈帧,就会先进入栈中,然后调用方法2,方法2的栈帧进入栈中,其次是方法3的栈帧3

最后:当方法3执行完毕,则方法3的栈帧先弹出(弹栈),然后是方法2的栈帧2,最后是栈帧1

3.1 垃圾回收是否涉及栈内存?

不涉及,垃圾回收指的是 回收 堆内存,当栈帧弹栈以后,内存就会释放

3.2 栈内存分配越大越好吗?

未必,默认的栈内存通常为1024K,也就是1MB

栈帧过大会导致线程数变少,例如,机器总内存为512MB,目前能活动的线程数就为512个(每个线程1MB),但是如果把栈内存改为2048K,也就是2MB,那么能够活动的栈帧就会减半

3.3 方法内的局部变量是否线程安全?

上面说到,在同一个虚拟机栈内,是线程安全的,但是就一定能说明方法内的局部变量是线程安全的吗?

不一定

如果方法内的局部变量没有逃离方法的作用范围,则这个局部变量是线程安全的

如果是局部变量引用了对象,并逃离方法的作用范围,则需要考虑线程安全的问题

3.4 栈内存会溢出吗

栈内存是线程私有的,会有内存溢出的问题吗?

有的兄弟,有的

1、栈帧过多导致的内存溢出,典型问题:递归调用

如下的无限递归调用,会导致栈帧有无限多个,导致栈内存溢出

2、栈帧过大导致栈内存溢出

这个不太容易出现,因为一个栈帧一般最大可以有1MB的内存大小,一般不会溢出

3.5 堆和栈的区别是什么

1、栈内存一般会用来存储局部变量、方法调用;但是堆内存是用来存储Java对象和数组的。

堆会GC垃圾回收,而栈不会

2、栈内存是线程私有的,而堆内存是线程共有的

3、两者内存溢出的报错不同:

栈空间不足:java.lang.StackOverFlowError

堆内存不足:java.lang.OutOfMemoreError

四 方法区(元空间)

1、方法区(Method Area)是各个线程共享的内存区间,用的是本地内存,也就是操作系统的内存

注意,是操作系统中的内存

2、主要存储类的信息、运行时常量池等

3、虚拟机启动的时候创建,关闭虚拟机时释放

4、如果方法区的内存无法满足分配请求,则会抛出OutOfMemoryError:MetaSpace

元空间是没有上限的,除非达到虚拟机内存的大小,或者你手动设值一个元空间的最大值

比如你通过如下命令:-XX:MaxMetaspaceSize=8m

修改元空间最大值为8MB,然后你开一个循环,使用ClassWriter加载10000个类,就可能把元空间撑爆:

MaxMetaspaceSize is too small

4.1 直接内存是什么?

直接内存不属于JVM的内存结构,不由JVM进行管理。是虚拟机的系统内存

常见于NIO操作时,用于数据缓冲区,分配回收成本较高,但读写能力高,不受JVM内存回收管理

因为Java代码是无法直接操作内存的,只能通过建立一个java缓冲区byte[],拷贝系统缓存区的数据,所以会比直接NIO操作直接内存来的慢

五 本地方法栈

本地方法栈(Native Method Stack)是JVM中为执行本地方法(Native Method)而准备的一块内存区域。本地方法指的是使用Java以外的语言(例如C或C++)编写,并通过JNI(Java Native Interface)或其他方式被Java程序调用的方法。

如果你在jdk中看到native修饰的方法,那么就是本地方法

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

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

相关文章

RAG(Retrieval-Augmented Generation)基建之PDF解析的“魔法”与“陷阱”

嘿,亲爱的算法工程师们!今天咱们聊一聊PDF解析的那些事儿,简直就像是在玩一场“信息捉迷藏”游戏!PDF文档就像是个调皮的小精灵,表面上看起来规规矩矩,但当你想要从它那里提取信息时,它就开始跟…

Python网络编程入门

一.Socket 简称套接字,是进程之间通信的一个工具,好比现实生活中的插座,所有的家用电器要想工作都是基于插座进行,进程之间要想进行网络通信需要Socket,Socket好比数据的搬运工~ 2个进程之间通过Socket进行相互通讯&a…

人工智能(AI)系统化学习路线

一、为什么需要系统化学习AI? 人工智能技术正在重塑各行各业,但许多初学者容易陷入误区: ❌ 盲目跟风:直接学习TensorFlow/PyTorch,忽视数学与算法基础。 ❌ 纸上谈兵:只看理论不写代码,无法解…

mac calDAV 日历交互

安装Bakal docker https://sabre.io/dav/building-a-caldav-client/ 在Bakal服务器上注册账户 http://localhost:8080/admin/?/users/calendars/user/1/ 在日历端登录账户: Server: http://127.0.0.1:8080/dav.php Server Path: /dav.php/principals/lion No e…

手机号登录与高并发思考

基础逻辑 一般来说这个验证码登录分为手机号、以及邮箱登录 手机号短信验证,以腾讯云SMS 服务为例: 这个操作无非对后端来说就是两个接口: 一个是获取验证码,这块后端生成6位数字expire_time 去推送到腾讯云sdk ,腾…

Python设计模式 - 适配器模式

定义 适配器模式(Adapter Pattern)是一种结构型设计模式,它用于将一个类的接口转换为客户端所期待的另一个接口。 注:在适配器模式定义中所提及的接口是指广义的接口,它可以表示一个方法或者一组方法的集合。 结构 …

【前端工程化】

目录 前端工程户核心技术之模块化前端模块化的进化过程commonjs规范介绍commonjs规范示例commonjs模块打包 amd规范、cmd规范前端工程化关键技术之npmwebpack原理 前端工程户核心技术之模块化 前端模块化是一种标准,不是实现。commonjs是前端模块化的标准&#xff…

关于CNN,RNN,GAN,GNN,DQN,Transformer,LSTM,DBN你了解多少

以下是神经网络中常见的几种模型的简要介绍: 1. ​CNN (Convolutional Neural Network, 卷积神经网络) ​用途: 主要用于图像处理和计算机视觉任务。​特点: 通过卷积核提取局部特征,具有平移不变性,能够有效处理高维数据(如图像…

T113-i开发板的休眠与RTC定时唤醒指南

​​在嵌入式系统设计中,休眠与唤醒技术是优化电源管理、延长设备续航的关键。飞凌嵌入式基于全志T113-i处理器开发设计的OK113i-S开发板提供了两种休眠模式:freeze和mem,以满足不同应用场景下的功耗与恢复速度需求。本文将详细介绍如何让OK1…

SpringBoot项目实战(初级)

目录 一、数据库搭建 二、代码开发 1.pom.xml 2.thymeleaf模块处理的配置类 3.application配置文件 4.配置(在启动类中) 5.编写数据层 ②编写dao层 ③编写service层 接口 实现类 注意 补充(注入的3个注解) 1.AutoWir…

高性能网络SIG双月动态:加速 SMC eBPF 透明替换特性上游化进程,并与上游深度研讨新特性

01、整体进展 本次双月报总结了 SIG 在 1 月和 2 月的工作进展,工作聚焦在 ANCK CVE 和稳定性问题修复,以及上游 SMC eBPF 透明替换特性推进和多个话题讨论上。 本月关键进展: 1. 推进 SMC eBPF 透明替换特性上游化,更新至 V7&…

某视频的解密下载

下面讲一下怎么爬取视频,这个还是比小白的稍微有一点绕的 首先打开网址:aHR0cDovL3d3dy5wZWFydmlkZW8uY29tL3BvcHVsYXJfNA 首页 看一下: 有一个标题和一个href,href只是一个片段,待会肯定要拼接, 先找一…

C++继承机制:从基础到避坑详细解说

目录 1.继承的概念及定义 1.1继承的概念 1.2 继承定义 1.2.1定义格式 1.2.2继承关系和访问限定符 1.2.3继承基类成员访问方式的变化 总结: 2.基类和派生类对象赋值转换 3.继承中的作用域 4.派生类的默认成员函数 ​编辑 默认构造与传参构造 拷贝构造&am…

测试基础入门

文章目录 软件测试基础1.1软件测试概述什么是软件测试什么是软件需求说明书软件测试的原则测试用例的设计测试用例设计的基本原则软件测试分类软件缺陷的定义 2.1软件开发模型软件开发模型概述大爆炸模型(边写边改)软件开发生命周期模型--螺旋模型软件开…

022-spdlog

spdlog 以下是从原理到代码实现的全方位spdlog技术调研结果,结合核心架构、优化策略和完整代码示例: 一、核心架构设计原理 spdlog三级架构 (图示说明:spdlog采用三级结构实现日志系统解耦) Registry管理中枢 全局…

STM32时钟树

时钟树 时钟树就是STM32中用来产生和配置时钟,并且把配置好的时钟发送到各个外设的系统,时钟是所有外设运行的基础,所以时钟也是最先需要配置的东西,在程序中主函数之前还会执行一个SystemClock_Config()函数,这个函数…

【第22节】windows网络编程模型(WSAAsyncSelect模型)

目录 引言 一、WSAAsyncSelect模型概述 二、WSAAsyncSelect模型流程 2.1 自定义消息 2.2 创建窗口例程 2.3 初始化套接字 2.4 注册网络事件 2.5 绑定和监听 2.6 消息循环 三、完整示例代码 引言 在网络编程的广袤天地中,高效处理网络事件是构建稳定应用的…

利用Dify编制用户问题意图识别和规范化回复

继上一篇文章,成功完成Dify本地部署后,主要做了一些workflow和Agent的应用实现,整体感觉dify在工作流可视化编排方面非常好,即使部分功能无法实现,也可以通过代码执行模块或者自定义工具来实现(后续再具体分…

双核锁步技术在汽车芯片软错误防护中的应用详解

摘要 本文深入探讨了双核锁步技术在保障汽车芯片安全性中的应用。文章首先分析了国产车规芯片在高安全可靠领域面临的软错误难点及攻克方向,然后详细介绍了双核锁步技术的基本原理及其在汽车芯片防软错误的重要性。通过对比国内外多家厂商的芯片技术,分析…

Lustre 语言的 Rust 生成相关的工作

目前 Lustre V6 编译器支持编译生成的语言为C语言。但也注意到,以 Rust 语言为生成目标语言,也存在若干相关工作。 rustre(elegaanz) 该项工作为 Lustre v6 语言的解析器,使用 Rust 语言实现。生成 Lustre AST。 项…