八股文总是忘?一张图牢记JVM内存结构|金三银四系列

金三银四又来啦!八股文还是得复习起来,最近准备把一些常见的八股文知识点聊聊。

本文详解了JVM内存结构和各个部分详细内容,应付面试绰绰有余!

点击上方“后端开发技术”,选择“设为星标” ,优质资源及时送达

JVM体系基本结构

学习JVM内存结构之前,首先要明白它在整个JVM体系中所处的位置。

JVM 体系主要是两个部分,JVM的内部体系结构分为三个子系统和两大组件,分别是:类装载器(ClassLoader)子系统、执行引擎子系统和GC子系统,组件是内存运行数据区域和本地接口。

类加载器子系统,GC子系统以及内存运行数据区域是我们研究的重点。

61a201904110b2bc37a2569e6c00fe7c.png

JVM 内存空间结构

JVM内存结构主要有五部分组成:程序计数器、方法区、虚拟机栈、本地方法栈、堆。

程序计数器(PC寄存器)

JVM中的程序计数器(Program Counter Register)又名 PC 寄存器,是线程私有的,Java虚拟机会为每个线程创建PC寄存器,与线程共存亡。PC寄存器是一块很小的内存空间(只存下一条指令的地址),几乎可以忽略不计。也是运行速度最快的存储区域。

5901c079b9b2f2be458c6c7a2846f685.png

作用:PC寄存器用来存储指向下一条指令的地址(即将要执行的指令代码),由执行引擎读取下一条指令。每执行一条指令 PC 都会自增,因此 PC 存储了指向下一条要被执行的指令地址。

注意,程序计数器并不是一个指针,它只是一个计数器,用于记录下一条要执行的字节码指令的位置,字节码指令通常是存储在方法区或者堆中的永久代(Permanent Generation)中。在方法区中,字节码指令存储在类的字节码文件中,当类被加载到内存中时,字节码文件就会被读取并存储到方法区中。在执行 Java 程序时,JVM 会从方法区中读取字节码指令,并将其解释执行或者编译执行。

可以看作是当前线程所执行的字节码的行号指示器,但是并不直接指向方法区的代码,他保存的地址才指向方法区字节码信息。

在任意时刻,一个 Java 线程总是在执行一个方法,这个方法称为当前方法。如果当前方法不是本地方法,PC寄存器总会执行当前正在被执行的指令,如果是本地方法,则PC寄存器值为Underfined。

Register的命名源于CPU的寄存器,寄存器存储指令相关的现场信息。CPU只有把数据装载到寄存器才能够运行。JVM中的PC寄存器是对物理PC寄存器的一种抽象模拟(即软件方面的)。

程序计数器是JVM中唯一一个没有 OOM异常的区域。

方法区(永久代)

方法区存储了每个类的信息(版本、字段、方法、接口等)、常量、静态变量、即时编译后的代码等数据。所有线程共享同一个方法区,因此访问方法区数据的和动态链接的进程必须线程安全。如果两个线程试图访问一个还未加载的类的字段或方法,必须只加载一次,而且两个线程必须等它加载完毕才能继续执行。

a9d6f20da0c4017696afceb03b043b92.png

永久代(Permanent Generation)是 HotSpot 的概念,方法区是 Java 虚拟机实现规范,JDK 1.7及之前,Hotspot 使用永久代实现方法区。JDK 1.8 开始 HotSpots 取消了永久代,引入元空间。元空间是直接存在内存中,不在 Java虚拟机中的,因此元空间依赖于内存大小,当然你也可以自定义元空间大小。

你可能对此有疑问。那么是不是就没有方法区了呢?

当然不是,方法区是一个规范,规范没变,它就一直在。那么取代永久代的就是元空间。原先永生代中类的元信息会被放入本地内存(元数据区,metaspace),将类的静态变量和内部字符串放入到java堆中。

在JDK1.7中存储在永久代的部分数据就已经转移到Java Heap或者Native memory。但永久代仍存在于JDK 1.7中,并没有完全移除,譬如符号引用(Symbols)转移到了native memory;字符串常量池(interned strings)转移到了堆中;JDK1.8开始,类的静态变量(class statics variables )转移到了Java heap;

eb2c4da13fd4832314475985796ceba3.png

方法区不需要连续的内存,可以选择固定大小或者可扩展。并且还可以选择不实现垃圾收集。相对而言,垃圾收集行为在这个区域是比较少出现的,但并非数据进入了方法区就如永久代的名字一样“永久”存在了。

这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载,一般来说这个区域的回收“成绩”比较难以令人满意,尤其是类型的卸载,条件相当苛刻,但是这部分区域的回收确实是有必要的。当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。

为什么引入元空间

元空间(Metaspace)是在JDK 1.8中引入的。在JDK 1.8之前的版本中,JVM使用永久代(Permanent Generation)来存储类的元数据信息,如类的字节码、方法、字段等信息。但是永久代的大小是有限制的,当加载的类或者应用程序使用的字符串常量等数据量较大时,可能会导致永久代的内存不足,从而引发OutOfMemoryError等问题。为了解决这个问题,JDK 1.8引入了元空间,它将类的元数据信息存储在堆外内存中,不再依赖于永久代,从而避免了永久代的内存限制问题。同时,元空间还支持动态调整大小,可以根据需要动态增加或缩减空间大小,提高了应用程序的灵活性。但是如果超过机器内存,也会出现OOM。

可以使用如下参数来调节方法区的大小:

JDK1.8之前调节方法区大小:

-XX:PermSize=N //方法区(永久代)初始大小

-XX:MaxPermSize=N //方法区(永久代)最大大小,超出这个值将会抛出OutOfMemoryError

JDK1.8开始方法区(HotSpot的永久代)被彻底删除了,取而代之的是元空间,元空间直接使用的是本机内存。参数设置:

-XX:MetaspaceSize=N //设置Metaspace的初始(和最小大小)

-XX:MaxMetaspaceSize=N //设置Metaspace的最大大小

虚拟机栈

Java虚拟机栈(Java Virtual Machine Stack),早期也叫Java栈。每个线程在创建时都会创建一个虚拟机栈,其内部存储一个个用于线程执行方法的栈帧(Stack Frame),每个方法在执行时都会创建一个栈帧并推入虚拟机栈顶。栈是线程私有的,生命周期和线程一致,也就是线程结束了。

ef760b645fa27a736df769112fbe560d.png

虚拟机栈中主要存放以下内容:

  1. 局部变量表:用于存储方法执行过程中的局部变量,包括基本数据类型、对象引用(类、数组、接口)以及returnAddress类型(指向方法返回地址的指针)。

  2. 操作数栈:用于存储方法执行过程中的操作数,包括方法参数、局部变量以及运算时的临时变量等。

  3. 方法返回地址:用于存储方法调用后的返回地址,以便方法执行完成后能够返回到原来的调用位置。

  4. 动态链接:用于存储方法调用的动态链接信息,包括指向该方法所在类的常量池中的方法符号引用和该方法在运行时常量池中的直接引用等。

栈上分配是什么?

栈上分配是指在方法调用时,如果一个对象满足一些特定条件(如对象的生命周期非常短,不逃逸出当前方法等),那么可以将这个对象分配在虚拟机栈中,而不是在堆中进行分配。这种方式称为栈上分配。

相比在堆中分配,栈上分配的优势在于可以避免对堆内存的频繁申请和释放,减少了垃圾回收器的负担,从而提高了程序的执行效率。

需要注意的是,虚拟机并不是所有的对象都可以进行栈上分配,只有在编译器能够确定对象的生命周期和作用域不会逃逸出当前方法时,才能进行栈上分配。否则,对象必须在堆中进行分配,并由垃圾回收器负责管理和回收。

栈上分配是一项高级优化技术,在某些情况下可以显著提高程序的性能。但需要注意的是,过度依赖栈上分配可能会导致栈溢出等问题,因此应该谨慎使用。

栈中可能出现的异常

Java 虚拟机规范允许Java栈的大小是动态的或者是固定不变的。

  • 如果采用固定大小的Java虚拟机栈,那每一个线程的Java虚拟机栈容量可以在线程创建的时候独立选定。如果线程请求分配的栈容量超过Java虚拟机栈允许的最大容量,Java虚拟机将会抛出一个StackOverflowError(给的固定内存不够) 异常。

  • 如果Java虚拟机栈可以动态扩展,并且在尝试扩展的时候无法申请到足够的内存,或者在创建新的线程时没有足够的内存去创建对应的虚拟机栈,那Java虚拟机将会抛出一个 OutOfMemoryError (无法申请足够的内存)异常。

本地方法栈

Java虚拟机栈于管理Java方法的调用,而本地方法栈用于管理本地方法(Native Method)的调用。本地方法栈,也是线程私有的。

允许被实现成固定或者是可动态扩展的内存大小。在内存溢出方面与Java栈是相同的,可能出现 StackOverflowError 和 OutOfMemoryError。

如果线程请求分配的栈容量超过本地方法栈允许的最大容量,Java虚拟机将会抛出一个StackOverflowError 异常。如果本地方法栈可以动态扩展,并且在尝试扩展的时候无法申请到足够的内存,或者在创建新的线程时没有足够的内存去创建对应的本地方法栈,那么Java虚拟机将会抛出一个OutOfMemoryError异常。(上面两点跟虚拟机栈一样)

本地方法是使用C语言实现的。

它的具体做法是Native Method Stack中登记native方法,在Execution Engine 执行时加载本地方法库(本地方法压入本地方法栈,然后给执行引擎获取(动态链接的方式),然后调用)。

堆(Heap)

应用系统对象都保存在Java堆中,堆被用来在运行时分配类实例、数组。堆上存储的对象在方法结束时不会被移除,只能由垃圾回收器移除。堆也是Java垃圾收集器管理的主要区域(所以很多时候会称它为GC堆),所有线程共享。

从GC回收的角度看,由于现在GC基本都是采用的分代收集算法,所以堆内存结构还可以分块成:新生代和老年代;再细一点的有Eden空间、From Survivor空间、To Survivor空间

7c7d7863e59f0b89a954c9e565a25d8f.png

为了给对象在内存中分配一块确定大小的空间,有两种堆内分配内存的方法,选择哪种分配方式由Java堆是否规整决定。

  1. 指针碰撞(Bump the Pointer):在堆内存中,用一个指针作为分界点,一侧为已经分配的内存,另一侧则是未分配的内存,当要分配内存时,只需要将指针向未分配的内存移动一段与对象大小相等的距离即可,分配出一块连续的内存空间来存储对象。(Serial、ParNew等带压缩过程的收集器采用)

  2. 空闲列表(Free List):在堆内存中,已经分配的内存和未分配的内存是交织在一起的,没有分界点,为了分配内存,需要维护一个空闲列表(Free List),记录哪些内存块是可用的,当需要分配内存时,从空闲列表中找到一块足够大小的空闲内存,然后将其分配给对象。分配内存后,需要从空闲列表中删除已分配的内存块,如果内存块被释放,那么需要将其加入到空闲列表中,方便下一次分配使用。(CMS这种基于标记清除Mark-Sweep算法的收集器采用)

总结

最后,我用一张图来总结今天的知识,大家收藏即可。

4c3800208f9bfcb794ddb19d884bc0e8.png

最后,欢迎大家提问和交流。

如果对你有帮助,欢迎点赞、评论或分享,感谢阅读!

无需注册直接体验ChatGPT!附注册ChatGPT详细教程

2023-02-09

655159fbe0a72e54ea2ede3dadf516f3.jpeg

一文掌握,单机Redis、哨兵和Redis Cluster的搭建,建议收藏

2023-02-11

c4160de435cbd1665ba788c69acfe20c.jpeg

MySQL事务ACID都知道,原理是什么?附面试题

2023-02-07

072bd0cf3545ed052ee1c4ac055b5586.jpeg

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

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

相关文章

【Android面试】2023最新面试专题:Java虚拟机原理(一)

1 描述JVM类加载过程 这道题想考察什么? 了解JVM是如何加载类的,并且通过JVM类加载过程能更直观了解掌握如APT注解处理器执行、热修复等技术的本质 考察的知识点 JVM类加载过程 考生如何回答 类加载的本质 一般情况下,类的数据都是在C…

JVM 锁优化和逃逸分析详解

1 锁优化 JVM 在加锁的过程中,会采用自旋、自适应、锁消除、锁粗化等优化手段来提升代码执行效率。 1.1 自旋锁和自适应自旋 现在大多的处理器都是多核处理器 ,如果在多核心处理器,有让两个或者以上的线程并行执行,我们可以让一个…

kubernetes学习之路--BadPods(Part1)

摘要:对Pod配置进行实战学习,以BadPods项目为例学习危险配置。 目录 一.BadPods介绍及使用 二.BadPods配置学习 2.1 less1--Everything allowed 基本操作学习 2.2 less1--Everything allowed 渗透学习 一.BadPods介绍及使用 项目地址:h…

基于GPT3.5实现本地知识库解决方案-利用向量数据库和GPT向量接口-实现智能回复并限制ChatGPT回答的范围...

标题有点长,但是基本也说明出了这篇文章的主旨,那就是利用GPT AI智能回答自己设置好的问题 既能实现自己的AI知识库机器人,又能节省ChatGPT调用的token成本费用。 代码仓库地址 document.ai: 基于GPT3.5的通用本地知识库解决方案 下面图片是整…

英语语法大全

文章目录 一、主语1、名词、代词和动词做主语2、主语从句做主语,谓语动词用单数3、主语从句练习 二、谓语动词1、谓语动词种类2、主谓一致 三、宾语1、单宾语2、双宾语3、复合宾语4、宾语从句 四、定语1、定语从句2、定语从句的翻译 五、状语1、分词做状语2、独立主…

规模效应和网络效应

前几天小米造车、华为造车、大疆造车、滴滴造车、百度造车集中PR。群中讨论智能新能源汽车的未来集中。甚至延伸讨论到了:云计算的未来集中度、SaaS的未来集中度。怎么能提高行业集中度,是我们都在苦苦思考的。 于是就讨论到两个词:规模效应、…

真*加班狗聚众舔福豹《打工人的那些事》

真*加班狗聚众舔福豹《打工人的那些事》 文章目录 近日的杭州金钱豹外逃新闻,相信大家都听说了。 没看过的也不急,我在这里帮大家简单理一理。 根据杭州市富阳区8日官方发布,5月7日20时许,群众报警称在富阳区银湖街道受降四联村…

国内“风口”转变,中国游戏公司纷纷“外逃”,东南亚是个好去处

中国游戏开发商正在加强对国际市场,特别是东南亚市场的承诺,因为他们的国内公司正在努力应对更困难的中国市场,以便实施在下一阶段发展布局。 根据移动应用市场情报公司Sensor Tower的一份报告,按收入排名的前100名全球移动游戏中…

chatgpt赋能python:Python编译成库的利与弊

Python编译成库的利与弊 Python作为一种高级编程语言,具有简洁易读的语法和强大的生态系统,在数据科学、Web开发、游戏开发等领域得到广泛应用。然而,Python解释器的执行效率较低,因此为了提高Python程序的性能,常使用…

产业大模型刚开卷,京东跑进“最后半公里”

点击关注 文|姚 悦 编|王一粟 “京东一直在探索哪些产品、技术、场景可以真正把大模型用起来,在我们内部的场景中反复验证后,才决定在7月份对外发布,现在我们在零售、健康、物流、金融等业务场景里已经积累了一些经…

赠书 | 写作、绘画、游戏、音视频编辑…AIGC为内容生产带来了什么?

文中有数据派THU福利哦 当AIGC产品不断涌向社会,人们纷纷认为美图app“危了“的时候,美图公司创始人兼首席执行官吴欣鸿表示,影像和 AIGC 的创新结合,将带来影像生产力的大爆发,同时会为相关领域带来新的职业和新的创业…

中文公开聊天语料库

源 / 专知 语料内容 该库搜集了包含chatterbot、豆瓣多轮、PTT八卦语料、青云语料、电视剧对白语料、贴吧论坛回帖语料、微博语料小黄鸡语料共8个公开闲聊常用语料和短信,并对其进行了统一化规整和处理,达到直接可以粗略使用的目的。 使用方法 语料下载&…

获得文本语料和词汇资源(基于nltk)

在自然语言处理的实际项目中,通常要使用大量的语言数据或者语料库。本章的目的是要回答下列问题: 什么是有用的文本语料和词汇资源,我们如何使用 Python 获取它们?哪些 Python 结构最适合这项工作?编写 Python 代码时…

NLP领域中文对话系统数据集总结(有下载地址)

一、豆瓣多轮对话数据集 1、简介: 测试数据包含 1000 个对话上下文,对于每个上下文,创建 10 个响应作为候选。正确的响应意味着响应可以自然地回复给定上下文的消息。每对收到三个标签,大多数标签被视为最终决定。 2、数据格式&…

肠道病毒组识别早产儿坏死性小肠结肠炎发病前的特异性病毒特征

期刊:Nature microbiology 影响因子:30.964 发表时间:2022 样本类型:粪便样本 研究背景 坏死性小肠结肠炎(NEC)是早产的严重后果,通常与肠道细菌微生物群的改变有关。然…

新型病毒来了【PcaPatchDbTask】

急报!!新型病毒来了【PcaPatchDbTask】 1.什么是PcaPatchDbTask PcaPatchDbTask是一种新型的木马 2.PcaPatchDbTask的危害 【1】他会劫持你的浏览器主页 【2】他会读取你的键盘信息 【3】他会获取你电脑的联系人菜单 【4】它甚至不会被安全软件查杀 3.…

Nature Reviews:给医生的菌群分析指南(下)

本文转载自“态昌基因”,己获授权。 Nature Reviews:给医生的菌群分析指南(上),主要从实验阶段介绍了以下7方面,不清楚的请点击链接跳转原文阅读。 1. 样本选择 2. 样本的采集 3. 样本的保存与保护剂 4. DNA提取 5.我到…

关于儿童急性感染性腹泻

腹泻是一种常见的症状,可导致儿童生长发育迟滞和营养不良。根据世界卫生组织(WHO)发布的数据显示,急性腹泻在5岁以下儿童死亡原因中排第二位,仅次于肺炎。引起儿童腹泻的原因包括感染和非感染因素,后者主要…

MPO抗体对丨CalBioreagents 中英文说明书

艾美捷CalBioreagents MPO抗体对英文参数说明: CATALOG NUMBER: M684 PRODUCT DESCRIPTION: Mouse Monoclonal anti-human Insulin IMMUNOGEN: Purified human MPO IMMUNOGLOBULIN ISOTYPE: IgG1 PURIFICATION: Purified by DEAE chromatography. BUFFER: Sup…

PICRUSt2菌群功能预测分析

生科云网址:https://www.bioincloud.tech 01 课程简介 PICRUSt2的原理是基于已测微生物基因组的序列,推断它们的共同祖先的基因功能谱,对数据库中其它未测物种(基因组未知)的基因功能谱进行推断,构建微生物…