【JVM】关于JVM的内部原理你到底了解多少(八股文面经知识点)

article/2025/7/16 20:27:45

前言

🌟🌟本期讲解关于HTTPS的重要的加密原理~~~

🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-CSDN博客

🔥 你的点赞就是小编不断更新的最大动力                                       

🎆那么废话不多说直接开整吧~~

 

目录

​编辑

📚️1.认识JVM

📚️2.JVM的内部解析

2.1JVM的内存区域划分

 1.堆区(只有一份)

 2.栈区(可以有N份)

3.程序计数器

4.元数据区

2.2JVM类加载机制

1.加载

2.验证

3.准备

 4.解析

5.初始化

2.3垃圾回收机制(GC)

1.GC的前言

2.回收的内存

3.识别垃圾

引用计数

可达性分析

4. 内存空间的释放

标记清除

复制算法

标记整理

分代回收

📚️3.总结


 

📚️1.认识JVM

在开始认识JVM的时候,这个本就不是我们工作中所运用得到的,那么我们在开始学习JAVA的时候,我们就听说过JVM,即如下三个:

jdk:Java开发工具包

jre:Java运行时环境

jvm:Java虚拟机

并且还了解过:编译型语言和解释型语言,而这里我们所学习的Java就是一个“半编译型”与“半解释型”的语言;

所以我们这里Java这样实现的目的就是为了跨平台,例如:C++编会编译成二进制的机器指令,而不同的CPU的机器指令是不一样的

具体的实现过程:

首先通过java.c将代码.java文件转化为.class字节码文件,然后再具体的系统平台上执行的时候,通过jvm将上述的字节码文件转化为CPU能够识别的机器语言

总结:所谓的jvm就是在Java编程中实现跨平台,充当中间人翻译官的角色

📚️2.JVM的内部解析

2.1JVM的内存区域划分

这里的jvm其实也是一个进程,那么我们之前在学习了解的计算机的工作原理:【后端开发】JavaEE初阶——计算机是如何工作的???-CSDN博客

了解到进程是需要操作系统分配内存空间的,这里支持了Java程序的执行,我们在Java程序中变量分配到的内存资源,其实就是jvm从操作系统内分配到的内存资源;而不同功能会对应分割不同的区域,这就是“内存的区域划分

这里的内存内部如下:

 1.堆区(只有一份)

即在代码中new出来的对象都是存储在这个区域里,对象中持有的非静态成员变量也是在这个堆里;

堆⾥⾯分为两个区域:新⽣代和⽼⽣代,新⽣代放新建的对象,当经过⼀定 GC 次数之后还存活的对象 会放⼊⽼⽣代。新⽣代还有 3 个区域:⼀个 Endn + 两个 Survivor(S0/S1),后面会将

 2.栈区(可以有N份)

本地方法栈/虚拟机栈,描述了方法的调用的关系,和局部变量

补充:

动态链接:指向运⾏时常量池的⽅法引⽤。
⽅法返回地址:PC 寄存器的地址
3.程序计数器

占有比较小的空间,专门又来存储下一条要执行的java程序指令的地址

4.元数据区

元数据区是一个计算机常见的概念,这里主要指定就是辅助性质的,描述性质的属性;

例如:在硬盘上,不仅仅要存储文件的数据信息,还有其他的辅助属性:“文件的大小,文件的存储位置,文件的拥有者,文件的访问权限”统称为元数据

那么此时就有如下的面试题:

class Test{private int n;private static int m;}public static void mian(String[] arg){Test t=new Test();
}

此时分析:n,t,m在内存区域的哪里???

n:由于n是一个成员变量,那么此时就是在堆上面的

t:是一个引用类型的局部变量,那么此时就是在栈上面

m:由于m是static修饰的变量,叫类对象,那么此时就是在元数据区里

被static修饰的变量叫类属性,修饰的方法叫类方法

非static修饰的变量叫实例属性,非修饰的方法叫实例方法 

所谓的类对象:就是Test.class,在.class文件加载到内存上面的时候,就会将信息用对象来表示,这个对象就是 类对象,包含了很多的属性

2.2JVM类加载机制

类加载:所谓的加载其实指定就是Java进程运行吧.class文件从硬盘读取到内存并进行一系列的校验解析的过程;

这里的加载的步骤主要分为5步

1.加载

 把硬盘上的.class文件找到,打开文件读取里面的内容(是一个二进制的数据)

重点(双亲委派模型)

所谓的双亲委派模型就是描述了如何查找.class文件的策略;

jvm在进行类加载的操作中,有个专门的模块称之为“类加载器”,这里的的类加载器默认是3个;

BootstrapClassLoader(负责查找目标库的目录)

ExtensionClassLoader(负责查找扩展库的目录)

ApplicationClassLoader(负责查找当前项目的代码目录,以及第三方库的目录)

注意:上述的三个类加载器的关系是父子关系,但是这里的父子关系指的就是二叉树的指针关系

具体的工作的流程:

ApplicationClassLoader入口进入,但是自己不会搜索自己负责的目录,而是会发给ExtensionClassLoader,同上也不会搜索,继续给父亲BootstrapClassLoader,然后由于没有父亲,那么就会开始目标库目录,如果找到了就直接进入打开文件,若没有找到,那么给ExtensionClassLoader开始搜索扩展库目录,同上找到了打开文件,没有继续给儿子;

最后没有找到会继续在孩子这一辈的类加载器搜索,但是默认 ApplicationClassLoader是没有孩子的,那么就会类加载失败,抛出ClassNotFountExecption

具体的模型如下:

优点: 

可以有效的避免自己写的类不小心和标准库的名字重复后,导致标准库的类功能失效

2.验证

当前需要知道保证读到的文件的内容是合法的.class文件内容

具体的验证的依据,在Java虚拟机规范中有明确的格式的说明:

解释:

u4:四字节无符号整数

u2:两个字节无符号整数

magic:魔幻数字,表示当前二进制的文件的格式是那种类型

field_info:另一个结构体

3.准备

 给类对象申请内存的空间,此时申请到的内存空间,里面默认值就全部是0(这个阶段的类对象中的静态成员变量的值就相当于是0)

 4.解析

主要针对的就是类中的字符串常量进行处理

例如:

class Test{private String s="Hello";
}

 那么此时的.class文件就会包含这个hello,那么此时的存储的情况就是如下的:

解释:

我们可以知道这里的s变量存储了hello的字符串常量的地址,那么在文件中不存在地址这个概念的,那么这里的红线就是偏移量来代替了地址; 

后面.class文件加载到内存中的时候,就可以直接替换成真实的“hello”的地址了;

5.初始化

就是针对这个类对象完成后续的初始化;还要执行静态代码块的逻辑,或者触发父类的加载

2.3垃圾回收机制(GC)

1.GC的前言

在C语言中,动态管理内存,那么就是molloc申请内存,free释放内存,那么此时申请的内存是跟随整个进程的,这一点对于服务器是非常不友好的,如果申请了内存不释放就会导致内存泄漏的问题,但是free需要手动调用,就会又不确定的因素

所以在java中就引入了自动释放内存的机制就是:GC

但是这里的C语言C++追求的是极致性能,所以就没有引入,因为垃圾回收有一个重要的问题

(stop the world)STW问题

当触发垃圾回收机制的时候,很有可能当前程序的其他的业务逻辑就会暂停;但是现在的STW的时间控制在1ms以内了,也是可以接受的

2.回收的内存

说到垃圾回收机制,我们知道在内存中的区域进行了分区的,那么垃圾回收,回收的是哪一部分的“垃圾”呢?

程序计数器:不需要GC

栈:不需要GC,局部变量在代码执行结束之后会自动的销毁,与垃圾回收没有关系

元数据区:不需要GC,这里只涉及类加载,很少涉及类卸载

堆:这里就是GC的主要战场

在垃圾回收中,跟准确的说法就是“回收对象” 

在堆中,内存的回收具体是如下所示的:

解释:

中间的那块,代表就是一半不回收,一半回收,一般就是不进行回收,叫做“骑强派” 这里包含的空闲的内存就不用管了

3.识别垃圾

所谓的垃圾识别就是判断出当前这个对象是否还继续进行使用,如果没有继续进行使用,那么这个对象就可以进行回收了;

具体举例:

void func{Test t=new Test();t.func1;
}

那么此时的情况就是如下的:

解释:

那么我们可以知道,局部变量的生命的周期是很短的,那么接下来在执行到“}”的时候,这里就被释放了,没有指向这个地址,那么这个堆里的对象就是垃圾了;

那么此时涉及下面的代码,那么就比较复杂了:

Test t1=new Test();
Test t2=t1;
Test t3=t2;

 那么就引入了一个新的概念,来解决这个问题复杂的情况;

引用计数

这种方法在JVM中并没有进行使用,那么此时主要是用在其他的主流的语言上面的(Python,PHP)

具体方法:

就是给对象安排一个额外的空间,来保存当前这个对象有几个引用

具体实例如下:

Test a=new Test();
Test b=a;
a=null;
b=null;

对应的图示:

解释:

此时我们可以看到,两个引用指向这个对象,那么申请空间的保存的就是2,两个引用,如果栈的局部变量被释放后,或者为“null”那么这个里面的引用就是0,此时就可以进行释放了;

缺点:

问题1:消耗额外的内存空间:如果对每个对象安排一个计数器,如果程序中的对象太多了,那么此时就会造成额外的空间消耗

问题2:引用计数器可能会导致“循环引用的问题”,应用计数就无法进行正常的工作了;

 什么是循环引用,具体代码如下:

class Test{Test t;
}Test a=new Test();
Test B=new Test();a.t=b;
b.t=a;
a=null;
b=mull;

那么具体的图示就是如下所示的:

解释:

那么此时就会发现,由于a.t=b,这个操作,导致在堆里的new的对象中多出来了一个地址的指向,那么此时就会发现,计数器中的值就是2,如果a,b都为null了,那么就会出现计数器为1,但是没有任何指向对象的引用; 

我们可以知道此时就相当于是死锁的情况了,两个对象不能调用,但是这两个对象却不是垃圾;那么此时就引入了另一个垃圾识别的分析

可达性分析

这里的可达性其实就类似于二叉树的遍历,若其中一个点被断了,那么后面的子结点就是不可达的,那么此时后面的就是垃圾,因该被回收了;

具体的情况图示如下:

解释:

如果此时的结点就都是可达的,若其中b=null,那么包括b和它的子结点都是不可达的,那么就是垃圾,就应该被回收了; 

4. 内存空间的释放

在上述的垃圾的识别标记后,那么此时就应该执行内存空间的释放的操作了,具体的内存释放的操作即如下三种的操作的方式

标记清除

做法:将标记的垃圾直接进行清除(直接释放掉)

具体的图示如下:

那么此时的黑色部分就是垃圾被清除的部分内存;

问题:

此时就造成了内存的碎片问题,因为在申请内存空间的时候是申请的一段连续的内存空间,此时就会造成内存总空间够,但是申请不了,因为内存不是连续的是断层的 

复制算法

做法:将不是垃圾的内存对象复制到另一半内存中,然后将复制前的内存空间连垃圾一起释放掉

那么此时的图示就是如下的:

解释:

那么此时就是将不是垃圾的内存对象复制到另一边,然后将左边区域直接全部释放掉,此时就直接规避了内存的碎片化的问题

 缺点:

缺点显而易见,就是总共可用的内存直接性的下降了,并且复制的对象很多的时候,复制的开销也会变大

标记整理

做法:类似与顺序表中的删除中间元素的操作(搬运),就是将非垃圾的内存对象把垃圾给覆盖掉

具体的实例如下:

解释:

此时就将非垃圾的内存对象给往前面进行搬运,这样就会解决内存碎片化问题,以及内存总空间减少的问题,但是会涉及到内存搬运的开销 

分代回收

做法:就是依据不同类的对象,采取不同的方式

此时就是jvm中有专门负责周期性的扫描,一个对象被扫描一次可达性满足,那么就会年龄+1;jvm机会根据年龄的差异把堆内存的空间分为两个部分,“新生代/老年代” 

具体的图示如下:

解释:

 new出来的新的对象就存储在伊甸区,经过扫描后,大部分的对象都直接GG,然后幸存下来的就在生存区,再次进行伊甸区和生存区的扫描,若在伊甸区就和上面一样,若是生存区,那么就拷贝到另一个区域,反复如此(每次扫描年龄+1)若若干轮的GC任然存在,那么就认为这个对象的生存的周期比较长,那么就会拷贝在老年区域了;(此时的扫描的频率就会下降)若老年区的对象变成垃圾了,那就会通过标记整理的方式进行释放内存;

ok以上就是垃圾回收的具体方法步骤,当然这里还涉及到“垃圾收集器”,小伙伴们可以去了解一下CMS,G1,ZGC这三个

📚️3.总结

💬💬本期小编主要总结了JVM面经的常考题,主要讲解了JVM的内部实现原理包括内存区域的划分,类加载机制,垃圾的回收机制(GC)从什么是垃圾,如何进行识别,到最后的内存对象的释放,都做了比较详细的介绍~~~

🌅🌅🌅~~~~最后希望与诸君共勉,共同进步!!!


💪💪💪以上就是本期内容了, 感兴趣的话,就关注小编吧。

                 😊😊  期待你的关注~~~


http://www.hkcw.cn/article/HkQsOSjiNB.shtml

相关文章

深入理解 JVM 的栈帧结构

🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c=1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编程,高并发设计,Springboot和微服务,熟悉Linux,ESXI虚拟化以及云原生Docker和K8s…

JVM 机制

目录 一、什么是 JVM: 二、JVM 的运行流程: 三、JVM 内存区域划分: 1、( 1 ) 程序计数器: 1、( 2 ) 元数据区: 1、( 3 ) 栈: 1、( 4 ) 堆: 四、类加载: 1、什么时候会触…

【JVM】类加载机制

文章目录 类加载机制类加载过程1. 加载2. 验证3. 准备4. 解析偏移量符号引用和直接引用 5. 初始化 类加载机制 类加载指的是,Java 进程运行的时候,需要把 .class 文件从硬盘读取到内存,并进行一些列的校验解析的过程(程序要想执行…

【JVM】从零开始深度解析JVM

本篇博客给大家带来的是JVM的知识点, 重点在类加载和垃圾回收机制上. 🐎文章专栏: JavaEE初阶 🚀若有问题 评论区见 ❤ 欢迎大家点赞 评论 收藏 分享 如果你不知道分享给谁,那就分享给薯条. 你们的支持是我不断创作的动力 . 王子,公主请阅🚀 …

一篇文章带你解决笔试面试中的jvm问题

JVM内存区域划分 JVM启动的时候,会申请到一整个很大的内存区域.JVM是一个应用程序,要从操作系统里申请内存.JVM就根据需要,把空间分为几个部分,每个部分各自有不同的功能.具体划分如下: 分为:栈,堆,程序计数器,元数据区 Heap(堆):…

通义灵码2.5——基于编程智能体开发Wiki多功能搜索引擎

引言 在智能化浪潮重塑软件开发范式的今天,我借助开发一个基于编程智能体开发Wiki 多功能搜索引擎,深度体验了通义灵码2.5这一阿里云旗舰级AI编码助手,构建智能协作新范式。 该平台通过三大技术突破赋能开发全流程:基于编程智能…

基于SpringBoot的商家销售管理网站的设计与实现

湖南软件职业技术大学 本科毕业设计(论文) 设计(论文)题目 基于SpringBoot的商家销售管理网站的设计与实现 学生姓名 学生学号 所在学院 专业班级 校内指导教师 企业指导教师 毕业设计(论文)真实性承诺及声明 学生对毕业设计(论文)真实性承诺 本人郑重声明:所提交的毕…

各种噪声电流激励下电源PDN网络对系统时钟性能的影响

点击上面“蓝字”关注我们 电源分配是支持所有类型硅产品运行的基础设施的重要组成部分,但在设计过程中常被忽视。电源质量可能限制电路性能,并决定其工作可靠性。要真正解决电源分配问题,必须考虑包括芯片、封装和PCB在内的整个系统。 芯片…

【大模型】情绪对话模型项目研发

一、使用框架: Qwen大模型后端Open-webui前端实现使用LLamaFactory的STF微调数据集,vllm后端部署, 二、框架安装 下载千问大模型 安装魔塔社区库文件 pip install modelscope Download.py 内容 from modelscope import snapshot_downlo…

关于位图Bitmaps的介绍

目录 1、基本概念 1.1、介绍 1.2、关键字 1.3、结构原理 2、常用命令 2.1、SETBIT 2.2、GETBIT 2.3、BITCOUNT 2.4、BITOP 2.5、BITPOS 3、应用场景 4、使用示例 前言 Redis的Bitmaps是一种基于字符串的数据结构,用于处理位级别的操作。 Bitmaps在Redis…

【软件设计】通过软件设计提高 Flash 的擦写次数

目录 0. 个人简介 && 授权须知1. Flash 和 EEROM 基本情况2. 场景要求3. 软件设计思路4. 代码展示4.1 flash.h4.2 flash.c 0. 个人简介 && 授权须知 📋 个人简介 💖 作者简介:大家好,我是喜欢记录零碎知识点的菜鸟…

C 语言练习--初级

#学习C 代码, 做小练习时,自己运行代码竟然发现很多错误,记录一下。 1、计算器 根据输入的数值和符合,输出相应结果。 结果: #include "stdio.h"int Primary_math(int a, int b, char sign){int num0;swit…

pikachu通关教程-CSRF XSS

XSS XSS漏洞原理 XSS被称为跨站脚本攻击(Cross Site Scripting),由于和层叠样式表(Cascading Style Sheets,CSS)重名,改为XSS。主要基于JavaScript语言进行恶意攻击,因为js非常灵活…

E. Melody 【CF1026 (Div. 2)】 (求欧拉路径之Hierholzer算法)

E. Melody 思路 将所有出现过的音量和音高看作一个点,一个声音看作一条边,连接起来。那么很容易知道要找的就是图上的一条欧拉路径(类似一笔画问题) 又已知存在欧拉路径的充要条件为:度数为奇数的点的个数为0或者2个…

历年中国科学技术大学计算机保研上机真题

2025中国科学技术大学计算机保研上机真题 2024中国科学技术大学计算机保研上机真题 2023中国科学技术大学计算机保研上机真题 在线测评链接:https://pgcode.cn/school?classification1 拆分数字 题目描述 给定一个数字,拆分成若干个数字之和&#xff…

2025陕西省赛补题

A 贪心 题意:给一个长度为n的序列,每次操作可以花费 w [ c [ i ] ] ( r − l 1 ) w[c[i]](r-l1) w[c[i]](r−l1)的代价,把区间 [ l , r ] [l,r] [l,r]染成染色 。 思路:对任意颜色,[l,r]中如果有cnt个连续的该颜色段…

Linux详谈进程地址空间

目录 第一谈:简单了解 第二谈:与操作系统的联系 内核空间与用户空间 步骤1:用户态代码执行 步骤2:跳转到内核代码 步骤3:内核代码访问用户数据 步骤4:返回到用户态 对于操作系统的本质:…

RabbitMQ vs MQTT:深入比较与最新发展

RabbitMQ vs MQTT:深入比较与最新发展 引言 在消息队列和物联网(IoT)通信领域,RabbitMQ 和 MQTT 是两种备受瞩目的技术,各自针对不同的需求和场景提供了强大的解决方案。随着 2025 年的到来,这两项技术都…

【Dify学习笔记】:Dify离线安装插件教程

Dify离线安装插件教程 1.本地下载插件 插件点击详情页面,安装右边的下载按钮,下载到本地 2.dify插件打包工具 dify-plugin-repackaging 下载后,进入到工具所在目录dify-plugin-repackaging/ git clone https://github.com/junjiem/dif…

2025年全国青少年信息素养大赛 scratch图形化编程挑战赛 小高组初赛 内部模拟试卷解析

2025年信息素养大赛初赛scratch模拟题 博主推荐 所有考级比赛学习相关资料合集【推荐收藏】 scratch资料 Scratch3.0系列视频课程资料零基础学习scratch3.0【入门教学 免费】零基础学习scratch3.0【视频教程 114节 免费】 历届蓝桥杯scratch国赛真题解析历届蓝桥杯scratch…