[线程与网络] Java虚拟机常考面试题(线程与网络完结)

🌸个人主页:https://blog.csdn.net/2301_80050796?spm=1000.2115.3001.5343
🏵️热门专栏:🍕 Collection与数据结构 (92平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm=1001.2014.3001.5482
🧀线程与网络(96平均质量分) https://blog.csdn.net/2301_80050796/category_12643370.html?spm=1001.2014.3001.5482
🍭MySql数据库(93平均质量分)https://blog.csdn.net/2301_80050796/category_12629890.html?spm=1001.2014.3001.5482
🍬算法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12676091.html?spm=1001.2014.3001.5482
感谢点赞与关注~~~
在这里插入图片描述

目录

  • 1. JVM内存划分
    • 1.1 堆区
    • 1.2 程序计数器
    • 1.3 元数据区
    • 1.4 Java虚拟机栈
    • 1.5 本地方法栈
    • 1.6 不同形态的变量在数据区中的存储
  • 2. JVM类加载
    • 2.1 类加载过程
    • 2.2 双亲委派模型
      • 2.2.1 什么是双亲委派模型
      • 2.2.2 工作过程
  • 3. JVM垃圾回收机制(GC)
    • 3.1 什么是GC
    • 3.2 GC的工作流程
      • 3.2.1 判断谁是垃圾
      • 3.2.2 释放对应内存(垃圾回收)

1. JVM内存划分

JVM本质上是一个Java进程,这个进程一旦跑起来,就会从操作系统中申请一大块内存空间.那么JVM接下来就要对这一大块空间进行划分,每个区域都有不同的功能.划分出来的也叫JVM运行时数据区或者也叫内存布局.
在这里插入图片描述

1.1 堆区

  • 堆区是各个数据区中最大的区域.
  • 他的作用是:程序中创建的所有对象都保存在堆中.
  • 这个区域是所有线程共享的.
  • 堆中分为两个区域,一个是新生代,一个是老年代,新生代中还有三个区域,一个是伊甸区(Eden),两个生存区(s1/s0).具体这几个区域中都存放什么样的对象,我们后面讲到垃圾回收机制的时候再说.
    在这里插入图片描述

1.2 程序计数器

  • 这个区域是数据区域中最小的区域.
  • 他的作用是:用来记录当前线程执行的行号.也就是当前要执行的下一条指令(JVM字节码)的地址,这个地址就是元数据区中的一个地址.
  • 这块区域是各个线程都有自己单独的一块,也就是线程私有的.

1.3 元数据区

  • 他的作用是:用来存储被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据.
  • 创建一个类之后产生的类对象就存储在这里.
  • 方法相关的信息也存储在这里,类中都有一些成员方法,每个方法都代表一系列"指令集合"(JVM字节码指令).
  • 这里还存储着常量池,不仅仅是string类型,也可能是数字等其他类型.
  • 这个区域是各个线程共享的.

1.4 Java虚拟机栈

  • 线程私有
  • Java虚拟机栈分为一下四部分:
    1. 局部变量表:存放了编译器可知的各种基本数据类型(8大基本数据类型)、对象引用。局部变量表所需的内存空间在编译期间完成分配,当进⼊⼀个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,在执行期间不会改变局部变量表大小。简单来说就是存放方法参数和局部变量
    2. 操作栈:每个方法会⽣成⼀个先进后出的操作栈。
    3. 动态链接:指向运行时常量池的⽅法引用。
    4. ⽅法返回地址:PC寄存器的地址。
      在这里插入图片描述

1.5 本地方法栈

  • 和Java虚拟机栈类似,
  • 也是线程私有的
  • 他两的区别就在于,Java虚拟机栈是给JVM使用的,而本地方法栈是给本地方法使用的.

1.6 不同形态的变量在数据区中的存储

基本原则:一个对象在哪个区域,取决于对应变量的形态.局部变量在栈上,成员变量在堆上,静态成员变量在元数据区.下面我们来举例说明:

class Test2{}
class Test{
	int a;
	Test2 t2 = new Test2();
	String s = "hello";
	static int b;
}
public static void main(String[] args){
	Test t = new Test();
}
  • main方法中的t变量在栈上,用来保存对象的首地址.(堆上的地址).
  • new Test()在堆上.是通过new创建出的一个对象.
  • new Test2()在堆上,和上一个是同理,也是通过new创建出的一个对象.
  • Test类中的成员变量都在堆上.
  • static修饰的是属于类的属性,就会出现在元数据区的类对象中.
    在这里插入图片描述

2. JVM类加载

一个Java进程要想跑起来,就要把Java先变成**.class文件.加载到内存中**,得到"类对象".这个所谓的跑起来,就是执行指令,要执行的CPU指令,都是通过字节码让JVM翻译出来的.

2.1 类加载过程

对于类加载的过程,总共分为一下几个步骤:

  1. 加载: 在硬盘上找到.class文件,读取文件内容.
  2. 连接
    • 验证:.class里的内容,是否符合要求.class文件格式的内容在官方文档中有明确的规定,把读取到的内容,往这一套标准中套入,即可判断是否符合要求
    • 准备:给类对象分配内存空间,分配之后,把这个空间里的数据先全部填充为0.
    • 解析:针对字符串常量初始化,把刚才.class文件中常量内容取出,放到元数据区.
  3. 初始化:针对类对象的初始化,其中就包含对静态成员初始化,执行初始化,执行静态代码块.注意不是针对对象的初始化.
    在这里插入图片描述

2.2 双亲委派模型

2.2.1 什么是双亲委派模型

在上述三部中,“加载"的过程中.会根据代码中"全限定类名”(包名+类名)找到对应的.class文件.在JVM加载.class文件,并找到.class文件的时候,就要用到双亲委派模型.
在JVM中包含这样一个特定的模块,叫做"类加载器",这个类负责完成后续的类加载工作.
如果⼀个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每⼀个层次的类加载器都是如此.

2.2.2 工作过程

在这里插入图片描述

  • 这其中有三个类加载器: AppClassLoader,ExtClassLoader,BootStrapClassLoader.这三个类加载器存在父子关系,如上图所示.
    [注意] 这里的父子关系不是通过类的继承方式来表示的,而是通过类加载器中的"parent"字段指向自己的父亲.
  • 三个类加载器的作用:
    • BootStrapClassLoader:加载标准库中的类.
    • ExtClassLoader:加载JVM扩展库中的类.(各JVM厂商,在上述的标准上,对JVM进行了扩展,这样的扩展在JVM标准之外,但是在安装了JVM就有.
    • AppClassLoader:加载第三方库的类和自己写的代码的类.
  • 他们几个类加载器的工作过程就类似于望父成龙的过程.
    • 工作从AppClassLoader开始,这个类加载器并不会立即搜索第三方库相关的目录.而是把任务交给自己的父亲来进行处理.也就是ExtClassLoader.
    • 工作到了ExtClassLoader,也不会立即对自己负责的扩展库进行搜索,也是把任务交给自己的父亲来处理.
    • 工作到了BootStrapClassLoader,BootStrapClassLoader也想交给自己的父亲进行处理.但是它的parent指向null,只能自己处理.在BootStrapClassLoader负责的标准库中的路径中搜索上述的类.
    • 如果找到了,就搜索完成了,类加载器负责打开文件,读取文件等后续操作.
    • 如果没有找到,任务还是要交给儿子来处理.
    • 工作回到ExtClassLoader,搜索扩展库的类,如果找到了,搜索完成,如果没找到,继续交给儿子处理.
    • 工作回到AppClassLoader,搜索第三方库中的类和自己创建的类.

举例说明:上司与下属处理问题
下属在发现一个问题的时候,不可以自己擅自处理,需要向上级上报,如果上报给上级之后,上级觉得这个问题非常重要,上级就会亲自处理,如果问题不是很重要,上级就会对下属说:"你自己看着办吧."于是下属就有权利处理这个问题了.

  • 双亲委派模型适用于:自己写的类和标准库/扩展库冲突,JVM会确保加载的类是标准库中的类.
  • 双亲委派模型可以破坏掉,我们可以通过自己实现类加载器来破坏模型.

3. JVM垃圾回收机制(GC)

3.1 什么是GC

这是Java提供的对于内存自动回收的机制.更本质地来说,GC其实回收的是"对象",回收的是"堆上的内存".回收对象的时候,一定是一次回收一个完整的对象,不能回收半个.
在这里插入图片描述

为什么GC只回收堆上的内存,不回收其他区域的?

  • 程序计数器:不需要额外回收,他是每个线程私有的,线程销毁之后,自然就回收了.
  • 栈:不需要额外回收,他是每个线程私有的,线程销毁之后,自然就回收了.
  • 元数据区:一般也不需要,都是加载类,很少卸载类.

3.2 GC的工作流程

GC的工作流程分为两步:

  1. 找到谁是垃圾
  2. 释放对应的内存

3.2.1 判断谁是垃圾

判定一个对象是否是垃圾,判定的方式比较保守.判定某个对象是否存在引用指向它.使用对象,都是通过引用的方式来使用的,如果没有引用指向这个对象,意味着这个对象无法再代码中使用.于是就可以视为垃圾.

  • 引用计数算法
    [注意] 这种算法是PHP和python采用的算法,不是JVM采用的算法.
    给对象增加⼀个引用计数器,每当有⼀个地方引用它时,计数器就+1;当引用失效时,计数器就-1;任何时刻计数器为0的对象就是不能再被使用的,即对象已"死".
    在这里插入图片描述
    但是这种方法存在很大的缺点,所以JVM才没有采用这样的方式.
    • 额外消耗的存储空间较大
    • 引用计数无法解决对象的循环引用问题
      什么是对象循环引用问题,我们来看下面这样一段代码.
    • 首先创建了两个对象,并使用a,b引用指向他们,对象的计数+1.
    • 之后两个对象中的t成员变量分别指向对方的引用,对象的计数+1.
    • 之后让a,b指向null,a,b指向的对象的计数-1,但是还没有减为零,所以两个对象没有被视为垃圾回收掉.
class Test{
	Test t;
}
public static void main(String[] args){
	Test a = new Test();
	Test b = new Test();
	a.t = b;
	b.t = a;
	a = null;
	b = null;
}

在这里插入图片描述

  • 可达性分析算法
    为了避免上述的两个问题,所以JVM引入了可达性分析算法.解决了空间和循环引用的问题.但是也付出了时间上的代价.
    这种算法的核心思想就是:遍历.
    JVM把对象之间的引用关系,理解为一个树形结构.JVM会不停遍历这样的结构,把所有可能遍历访问到的对象标记为"可达",剩下的是"不可达".
    例如下面这棵树:
    在这里插入图片描述

从root出发,任何一个树上的结点都可达.
如果现在令c.right = null,这样的话,f也无法访问到了,f就会被标记为"不可达",就会把f标记为垃圾.a.right = null,此时c就不可达,f也不可达,c和f也会被标记为垃圾.
JVM会周期性对所有的树进行遍历,不停标记可达/不可达.

3.2.2 释放对应内存(垃圾回收)

把垃圾标记出来之后,就要对垃圾进行回收操作了.

  • 标记-清除算法
    这个算法分为标记和清除两个阶段.首先需要标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象.
    但是这种算法有一些不足:
    • 效率问题:标记和清除这两个过程的效率都不高.
    • 空间问题:标记清除之后会产生大量的不连续的内存碎片,空闲的内存被分成了一个碎片,不集中.空间碎片太多可能会导致以后子啊程序运行的时候需要分配较大对象的时候,无法找到足够连续的内存.
      在这里插入图片描述
  • 复制算法
    当这块内存需要进行垃圾回收时,会将此区域还存活着的对象复制到另⼀块上面,然后再把已经使用过的内存区域⼀次清理掉.
    在这里插入图片描述
    但是这种做法也有一个致命的缺点:复制的时间开销很大.
  • 标记-整理算法
    标记过程仍与"标记-清除"过程⼀致,但后续步骤不是直接对可回收对象进行清理,而是让所有存活对象都向⼀端移动,然后直接清理掉端边界以外的内存.;类似于顺序表删除中间元素的操作.
    在这里插入图片描述
    这种算法实质上和复制算法差别不大,也是会涉及到复制操作,也会产生较大的时间开销.
  • 分代算法
    这种算法就是根据对象的年龄进行垃圾回收.所谓的年龄就是经过GC扫描的次数.按照年龄,把对象分为新生代和老年带,其中新生代又分为伊甸区和生存区.这就和我们前面所提到的堆的数据区接轨了.
    在这里插入图片描述
    • 新创建的对象,会被放到伊甸区,伊甸区的大部分对象,生命周期都比较短,第一轮GC就有可能成为垃圾,只有极少数可以活过第一轮来到生存区.
    • 生存区有两个,每经过一轮GC,生存区都会淘汰一批对象,剩下的进入到另一个生存区,到达另一个生存区是通过复制实现的.此外还有伊甸区新来的对象.每复制一次,年龄+1.就这样在两个生存区之间来回周转.
    • 老年代对象也要经过GC,但是老年代的生命周期更长,就可以降低GC的频率.这里对老年代的GC,是通过标记=整理算法来完成的.

举例说明:校招找工作

  • 伊甸区:投放简历,大量简历被直接淘汰
  • 生存区:简历通过,要经过笔试,技术面,HR面等多轮筛选.
  • 老年代:进入公司,但是会定期考核.

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用 GPT-4 创作高考作文 2024年

使用 GPT-4 创作高考作文 2024年 使用 GPT-4 创作高考作文:技术博客指南 🤔✨摘要引言正文内容(详细介绍) 📚💡什么是 GPT-4?高考作文题目分析 ✍️🧐新课标I卷 人类智慧的进步&…

atomic特质的局限性

为什么在实际的 Objective-C 开发中, 几乎所有的属性都声明为 nonatomic ? 声明为 atomic 的属性我是真的没见过 在实际的 Objective-C 开发中,大多数属性通常声明为 nonatomic,主要原因包括性能考虑和常见的设计模式。具体原因如下: 性能问…

openai 前员工释放出关于AGI的前世今生和未来发展趋势的详细报告

目录 1.引言2.AGI的临近3.投资与工业动员4.国家安全与AI竞赛5.技术挑战与机遇6.项目与政策7.结语8.原文PDF链接PS.扩展阅读ps1.六自由度机器人相关文章资源ps2.四轴机器相关文章资源ps3.移动小车相关文章资源 1.引言 2024年,我们站在了一个全新的科技前沿。在这篇文…

【wiki知识库】06.文档管理页面的添加--前端Vue部分

📝个人主页:哈__ 期待您的关注 目录 一、🔥今日目标 二、🐻前端Vue模块的改造 BUG修改 1.wangeditor无法展示问题 2.弹窗无法正常关闭问题 2.1 添加admin-doc.vue 2.1.1 点击admin-ebook中的路由跳转到admin-doc 2.2.2 进入…

9.2 Go 接口的实现

💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

在Ubuntu中进行PX4配置的过程中出现以下报错,且不能正常打开gazebo

🏆本文收录于「Bug调优」专栏,主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&…

【MATLAB源码-第222期】基于matlab的改进蚁群算法三维栅格地图路径规划,加入精英蚁群策略。包括起点终点,障碍物,着火点,楼梯。

操作环境: MATLAB 2022a 1、算法描述 蚁群算法(Ant Colony Optimization,ACO)是一种通过模拟蚂蚁觅食行为的启发式优化算法。它由意大利学者Marco Dorigo在20世纪90年代初提出,最初用于解决旅行商问题(T…

Docker高级篇之Docker网络

文章目录 1. Docker Network简介2. Docker 网络模式3. Docker 网络模式之bridge4. Docker 网络模式之host5. Docker 网络模式之none6. Docker 网络模式之container7. Docker 网络模式之自定义网络模式 1. Docker Network简介 从Docker的架构和运作流程来看,Docker是…

LeMeViT:具有可学习元令牌的高效ViT

本文提出使用可学习的元令牌来制定稀疏令牌,这有效地学习了关键信息,同时提高了推理速度。从技术上讲,主题标记首先通过交叉关注从图像标记中初始化。提出了双交叉注意(DCA)来促进图像令牌和元令牌之间的信息交换&…

MATLAB入门知识

目录 原教程链接:数学建模清风老师《MATLAB教程新手入门篇》https://www.bilibili.com/video/BV1dN4y1Q7Kt/ 前言 历史记录 脚本文件(.m) Matlab帮助系统 注释 ans pi inf无穷大 -inf负无穷大 i j虚数单位 eps浮点相对精度 0/&a…

设计软件有哪些?效果工具篇(3),渲染100邀请码1a12

这次我们再介绍一批渲染效果和后期处理的工具。 1、ColorCorrect ColorCorrect是一种图像处理技术,用于调整图像的色彩和对比度,使其更加自然和平衡。通过ColorCorrect,用户可以调整图像的色调、亮度、饱和度等参数,以达到理想的效…

关于CodeCombat(沙漠)布朗噪声的攻略

关于CodeCombat(沙漠)//布朗噪声的攻略 总的来说怎么猥琐怎么来 1.走到墙角骷髅看不到的位置,让宠物制造噪音,然后英雄走过去,就是这样没错(坐标之类能明白) 最后看看运行结果吧 Rec 0002 希望天天开心

FreeRTOS基础(十三):队列集

队列集(Queue Set)通常指的是一组队列,它们可以用于处理不同的任务或数据流。每个队列可以独立地处理自己的元素,但作为一个集群,它们可以协同工作来完成更复杂的任务。下面进行介绍。 目录 一、队列集简介 二、队列…

【JS】理解闭包及其应用

历史小剧场 明朝灭亡,并非是简单的政治问题,事实上,这是世界经济史上的一个重要案例。 所谓没钱,就是没有白银。----《明朝那些事儿》 什么是闭包? 闭包就是指有权访问另一个函数作用域中变量的函数 闭包变量存储位置&…

六、【源码】SQL执行器的定义和实现

源码地址:https://github.com/mybatis/mybatis-3/ 仓库地址:https://gitcode.net/qq_42665745/mybatis/-/tree/06-sql-executor SQL执行器的定义和实现 之前的Sql执行都是耦合在SqlSession里的,现在要对这部分进行解耦和重构,引…

1奇函数偶函数

文章目录 自变量有理化奇偶性周期性初等函数 自变量 自变量是x,这个还挺奇怪,记住就好 y f ( e x 1 ) yf(e^x1) yf(ex1) 里面 e x e^x ex 只算中间变量,自变量是x 做这些题,想到了以前高中的时候做数学题,不够扎实…

Java 18 的主要新特性和代码演示

默认 UTF-8 从 JDK8 开始,UTF-8 就是 Java SE API 的默认字符集。java.nio.charset.Charset#defaultCharset() 现在默认返回 UTF-8 。现在 Java 的标准 API 都默认使用 UTF-8 编码,目的是让 Java 程序可预测和可移植。在之前, 读取同一个文件…

从《千脑智能》看大模型

千脑智能与大模型 千脑智能介绍 世界模型千脑智能理论——对大脑的全新理解旧大脑:演化的历史烙印新大脑:智慧的创新引擎新旧大脑的互动与争斗启示与借鉴 大脑对信息的处理和建模六根六尘六识 新脑:智能的创新中枢旧脑:生存的本能…

数据结构笔记 4 树和二叉树

二叉树和完全二叉树的区别? 二叉树和完全二叉树的主要区别在于它们的结构特性和节点排列方式: 1. **二叉树**: - 是一种数据结构,其中每个节点最多有两个子节点,通常称为左子节点和右子节点。 - 节点的子节点数量…

用爬虫实现---模拟填志愿

先来说实现逻辑,首先我要获取到这个网站上所有的信息,那么我们就可以开始对元素进行检查 我们发现他的每一个学校信息都有一个对应的属性,并且是相同的,那么我们就可以遍历这个网页中的所有属性一样的开始爬取 在来分析&#xff0…