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

前言

🌟🌟本期讲解关于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.rhkb.cn/news/470760.html

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

相关文章

【Pikachu】目录遍历实战

既然已经决定做一件事,那么除了当初决定做这件事的我之外,没人可以叫我傻瓜。 1.目录遍历漏洞概述 目录遍历漏洞概述 在Web功能的设计过程中,开发者经常会将需要访问的文件作为变量进行定义,以实现前端功能的灵活性。当用户发起…

如何用C#和Aspose.PDF实现PDF转Word工具

在本篇博文中,我将详细讲解如何用C#实现一个PDF转Word工具。这款工具基于Aspose.PDF库,实现PDF文件转为Word(DOC/DOCX)格式的功能,并通过用户友好的界面和状态提示提升用户体验。希望通过这篇文章帮助大家理解软件的实…

【图像压缩感知】论文阅读:Self-supervised Scalable Deep Compressed Sensing

tips:本文为个人阅读论文的笔记,仅作为学习记录所用。 Title:Self-supervised Scalable Deep Compressed Sensing Journal:IJCV 2024 代码链接:GitHub - Guaishou74851/SCNet: Self-Supervised Scalable Deep Comp…

使用elementUI实现表格行拖拽改变顺序,无需引入外部库

前言: 使用vue2element UI,且完全使用原生的拖拽事件,无需引入外部库。 如果表格数据量较大,或需要更多复杂功能,可以考虑使用 vuedraggable库,提供更多配置选项和拖拽功能。 思路: 1. 通过el-table的ro…

深入理解接口测试:实用指南与最佳实践5.0(三)

✨博客主页: https://blog.csdn.net/m0_63815035?typeblog 💗《博客内容》:.NET、Java.测试开发、Python、Android、Go、Node、Android前端小程序等相关领域知识 📢博客专栏: https://blog.csdn.net/m0_63815035/cat…

32位、64位、x86与x64:深入解析计算机架构

目录 一、32位架构(x86) 1.1 定义与历史 1.2 技术特点 1.3 优缺点 二、64位架构(x64) 2.1 定义与历史 2.2 技术特点 2.3 优缺点 三、x86与x64的关系 四、应用场景 4.1 32位架构的应用场景 4.2 64位架构的应用场景 五、总结 在计算机领域中,处理器架构的选择对…

【stable diffusion部署】超强AI绘画Stable Diffusion,本地部署使用教程,完全免费使用

前言 01 软件介绍 Stable Diffusion和Midjourney类似,都是当下AI绘画最流行的AI工具之一,都支持用文字生成AI图片或者图片生成图片的软件。 二者的区别是:Midjourney只能在网上使用,国内需要魔法才能使用,而且存在使…

【计算机网络】【网络层】【习题】

计算机网络-传输层-习题 文章目录 13. 图 4-69 给出了距离-向量协议工作过程,表(a)是路由表 R1 初始的路由表,表(b)是相邻路由器 R2 传送来的路由表。请写出 R1 更新后的路由表(c)。…

【嵌入式开发】单片机CAN配置详解

0 前言 CAN外设作为一种传输速率较高,且连线较为简洁的通信协议,如今很多单片机内部都集成了CAN控制模块,这样只需要再外接一个CAN收发芯片,将TTL/CMOS电平转换成CAN协议的差分电平,就是一个完整的CAN收发节点。   最…

虚拟机安装Ubuntu 24.04服务器版(命令行版)

这个是专门用于服务器使用的,没有GUI,常用软件安装,见 虚拟机安装Ubuntu 24.04及其常用软件(2024.7)_ubuntu24.04-CSDN博客https://blog.csdn.net/weixin_42173947/article/details/140335522这里只记录独特的安装步骤 1 下载Ubuntu 24.04安…

ctfshow-web入门-SSTI(web361-web368)上

目录 1、web361 2、web362 3、web363 4、web364 5、web365 6、web366 7、web367 8、web368 1、web361 测试一下存在 SSTI 注入 方法很多 (1)使用子类可以直接调用的函数来打 payload1: ?name{{.__class__.__base__.__subclasses__…

Axure网络短剧APP端原型图,竖屏微剧视频模版40页

作品概况 页面数量:共 40 页 使用软件:Axure RP 9 及以上,非软件无源码 适用领域:短剧、微短剧、竖屏视频 作品特色 本作品为网络短剧APP的Axure原型设计图,定位属于免费短剧软件,类似红果短剧、河马剧场…

如何从头开始构建神经网络?(附教程)

随着流行的深度学习框架的出现,如 TensorFlow、Keras、PyTorch 以及其他类似库,学习神经网络对于新手来说变得更加便捷。虽然这些框架可以让你在几分钟内解决最复杂的计算任务,但它们并不要求你理解背后所有需求的核心概念和直觉。如果你知道…

JS 实现SSE通讯和了解SSE通讯

SSE 介绍: Server-Sent Events(SSE)是一种用于实现服务器向客户端实时推送数据的Web技术。与传统的轮询和长轮询相比,SSE提供了更高效和实时的数据推送机制。 SSE基于HTTP协议,允许服务器将数据以事件流(…

HTML之表单学习记录

如果一个页面仅仅供用户浏览,那就是静态页面。如果这个页面还能实现与服务器进行数据交互(像注册登录、话费充值、评论交流)​,那就是动态页面。表单是我们接触动态页面的第一步。其中表单最重要的作用就是:在浏览器端…

WPF学习之路,控件的只读、是否可以、是否可见属性控制

C#的控件学习之控件属性操作 控件的只读、是否可以、是否可见,是三个重要的参数,在很多表单、列表中都有用到,正常表单控制可以在父层主键控制参数是否可以编辑和可见,但是遇到个别字段需要单独控制时,可以在初始化wi…

three.js 杂记

clip: 1: 着色器 #ifdef USE_CLIP_DISTANCE vec4 worldPosition modelMatrix * vec4( position, 1.0 ); gl_ClipDistance[ 0 ] worldPosition.x - sin( time ) * ( 0.5 ); #endif gl_Position projectionMatrix * modelViewMatrix * vec4( positio…

基于混合配准策略的多模态医学图像配准方法研究

摘要: 提出了一种由“粗”到“细”的混合配准策略,该配准策略吸取了以往配准方法的优点,且在细配阶段将基于特征的配准方法和基于灰度的配准方法结合在一起,提出了基于轮廓特征点集最大互信息的配准方法,从而在速度和精…

贪心算法入门(二)

相关文章 贪心算法入门(一)-CSDN博客 1.什么是贪心算法? 贪心算法是一种解决问题的策略,它将复杂的问题分解为若干个步骤,并在每一步都选择当前最优的解决方案,最终希望能得到全局最优解。这种策略的核心…

Autosar CP 基于CAN的时间同步规范导读

Autosar CP 基于CAN的时间同步规范主要用途 实现精确时间同步 提供了一种在CAN总线上准确分发时间信息的机制,确保连接到CAN网络的各个电子控制单元(ECU)能够共享精确的公共时间基准,对于需要精确时间协调的汽车系统功能&#xff…