JVM篇--垃圾回收高频面试题

JVM垃圾回收

1 简单说下Java垃圾回收机制?

首先在java运行过程中,其实程序员并不需要去显示的调用程序来释放对象的内存,而是由虚拟机来完成的,具体来看是在jvm中有个垃圾回收线程,这个线程是个守护线程,这个线程会在虚拟机空闲或者在当前堆内存不足时,才会触发执行,扫面那些没有被任何引用的对象,并将它们添加到要回收的集合中,进行回收。

2 垃圾回收器的基本原理是什么?优点有哪些,垃圾回收器可以马上回收内存吗?

其实jvm的垃圾回收,在我们一开始创建对象的时候,GC就会去监控这个对象的地址,大小和使用情况,而jvm在进行回收的时候主要是采用了可达性分析算法,通过这种方式确定哪些对象是"可达
的",哪些对象是"不可达的"。当GC确定一些对象为"不可达"时,GC就有责任回收这些内存空间。
其实垃圾回收的优点也很明显,首先就是不用像其他语言一样需要程序员手动的去释放内存,其次垃圾回收机制可以有效的防止内存泄露,并且可以做到对内存进行更有效的利用
对于垃圾回收的时机,虽然程序员可以通过执行System.gc(),通知GC运行,但是Java语言规范并不保证GC一定会执行。

3 怎么判断对象是否可以被回收?

我们刚才说到jvm会自动的对内存进行回收,因此它在回收的时候就需要知道 哪些对象是存活的,不需要被回收;而哪些对象又是垃圾对象,可以被回收,那么它具体是怎么判断的呢?
其实有两种判断方式
1 引用计数法:说白了也就是会为每一个对象创建一个引用计数,有对象引用时,计数器会加1,而引用释放时计数器会减1,而当计数器为0时也就表示对象可以被回收,它有一个缺点就是不能解决循环引用的问题
2 可达性分析算法:也就是会从GC root开始向下搜索,搜索所走过的路径称为引用链。当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象是可以被回收的。

4 JVM 运行时 堆内存如何分代?

Java 堆从 GC 的角度还可以细分为: 新生代和老年代。
而新生代 又可以分为 (Eden 区、 From Survivor 区和 To Survivor 区)
一般新生代和老年代的比例约为 1:2
同时 eden区:s1区:s2区约为 8:1:1
在这里插入图片描述
同时对于新生代来说 JVM 每次只会使用 Eden 和其中的一块 Survivor 区域来为对象服务,所以无论什么时候,总是有一块 Survivor区域是空闲着的。
整体的流程就是 :新建的对象会首先分配在Eden区中,经历一次Minor GC,Eden中的存活对象就会被移动到第一块survivor S0区,Eden被清空;等Eden区再满了,就再触发一次Minor GC,Eden和S0中的存活对象又会被复制送入第二块survivor S1 区,就是通过这样不断地复制–>清空—>互换来实现年轻代的垃圾回收即minor gc
同时年轻代采用复制算法,也解决了内存碎片化的问题

我们接着再看老年代
老年代的对象特点 一般都是长生命周期的对象,也就是比较稳定,因此 MajorGC (常常称之为 FULL GC)不会频繁执行。
同时注意在进行 FULL GC前一般都先进行了一次 MinorGC,使得有新生代的对象晋身入老年代,导致空间不够用时才触发。当无法
找到足够大的连续空间分配给新创建的较大对象时也会提前触发一次 MajorGC 进行垃圾回收腾出空间。

FULL GC 采用标记清除算法,同时会产生内存碎片

永久代 (或者 jdk1.8元空间)
指内存的永久保存区域,主要存放 Class 和 Meta(元数据)的信息,Class 在被加载的时候被放入永久区域, 它和和存放实例的区域不同,GC 不会在主程序运行期对永久区域进行清理。所以这也导致了永久
代的区域会随着加载的 Class 的增多而胀满,最终抛出 OOM 异常。

5 JVM内存为什么要分成新生代,老年代,永久代(即为什么要分代)?新生代中为什么要分为Eden和Survivor?

这个问题 其实想一下就能理解 分代主要还是 为了提高对象内存分配和垃圾回收的效率。
试想一下,如果堆内存没有区域划分,所有的新创建的对象和生命周期很长的对象放在一起,随着程序的执行,堆内存需要频繁进行垃圾收集,而每次回收都要遍历所有的对象,遍历这些对象所花费的时间代价是巨大的,会严重影响我们的 GC 效率

而有了内存分代,情况就不同了,新创建的对象会在新生代中分配内存,经过多次回收仍然存活下来的对象存放在老年代中,
静态属性、类信息等存放在永久代(或者元空间)中,
新生代中的对象存活时间短,只需要在新生代区域中频繁进行 GC,老年代中对象生命周期长,内存回收的频率相对较低,不需要频繁进行回收。

而新生代为什么要分为eden区和survivor区 ?

  1. 我们试想下 如果没有Survivor,Eden区每进行一次Minor GC,存活的对象就会被送到老年代。这样一来老年代很快被填满,触发Major GC.
    又因为老年代的内存空间远大于新生代,进行一次Full GC消耗的时间比Minor GC长得多,
    所以总结来看 分为eden区 和s区可以减少对象频繁地被输送到老年代,进而减少了full gc的发生。
  2. 同时分为两个eden区,利用这种复制算法也避免了内存的碎片化。

6 JVM中一次完整的GC流程是怎样的,对象如何晋升到老年代?

针对这个问题,思路就是可以先描述下java堆内存的划分,以及minor gc,major gc,full gc 以及他们之间的转换过程。
首先我们知道java堆可以分为 老年代 + 新生代;同时 新生代 = Eden + S0 + S1
整体的过程就是:

  1. 当 Eden 区的空间满了, Java虚拟机会触发一次 Minor GC,以收集新生代的垃圾,存活下来的对象,则会转移到 Survivor区
  2. 而 如果对象在Eden出生,并经过第一次Minor GC后仍然存活,并且被Survivor容纳的话,年龄设为1,每熬过一次Minor GC,年龄+1,若年龄超过一定限制(15)----即经过静态年龄判断规则后,则被晋升到老年态。即长期存活的对象进入老年态。
    当然对于大对象 (比如那种连续内存空间的java对象,比如那种很长的字符串)也会直接进入老年代
  3. 当老年代满了无法容纳更多的对象,就会发生major gc清理掉老年代,同时major gc会伴随着至少一次minor gc。
  4. 而Full GC 会清理整个内存堆 – 包括年轻代和年老代。

那么Minor GC与Full GC分别在什么时候发生?
新生代内存不够用时候发生minor gc也叫YGC;JVM内存不够的时候发生FGC

7 JVM 有哪些垃圾回收算法?

可以分为 四种,即标记-清除算法;复制算法;标记整理算法; 分代收集算法;
我们首先看标记清除算法
该算法分为“标记”和“清除”阶段:首先标记出所有不需要回收的对象,在标记完成后统一回收掉所有没有被标记的对象。
适用场合:存活对象较多的情况、适用于年老代。
优点:比较简单,不需要对象的移动
缺点:会产生大量的内存碎片;效率也比较低

复制算法
因为标记清除算法会产生内存碎片 因此在他的基础之上引入复制算法
说白了复制算法 就是 把内存空间划为两个相等的区域,每次只使用其中一个区域。
垃圾收集时,遍历当前使用的区域,把存活对象复制到另外一个区域中,最后将当前使用的区域的可回收的对象进行回收。
优点:按顺序分配内存即可,实现简单、运行高效,不用考虑内存碎片
缺点:可用的内存大小缩小为原来的一半,对象存活率高时会频繁进行复制。
在这里插入图片描述

标记整理算法
刚才说了复制算法 解决了内存碎片化的问题,但是它也有一个问题,就是内存的使用率并不高,需要频繁地进行来回复制,
因此又引入了标记整理算法,说白了 就是在标记可回收的对象后将所有存活的对象压缩到内存的一端,使他们紧凑的排列在一起,然后对端边界以外的内存进行回收。回收后,已用和未用的内存都各自一边。
优点是:解决了内存碎片化的问题,相比于复制算法 内存使用率也提高了
缺点:仍需要进行局部对象移动,一定程度上降低了效率
在这里插入图片描述
分代收集算法:
分代收集法是目前大部分 JVM 所采用的方法,顾名思义是根据对象的存活周期将内存划分为几块。一般包括年轻代、老年代 和 永久代,并根据各年代特点分别采用最适当的 GC 算法
老生代的特点是每次垃圾回收时只有少量对象需要被回收,
新生代的特点是每次垃圾回收时都有大量垃圾需要被回收,
因此可以根据不同区域选择不同的算法
在这里插入图片描述
新生代与复制算法
每次垃圾收集都能发现大批对象已死, 只有少量存活. 因此选用复制算法, 只需要付出少量存活对象的复制成本就可以完成收集,当然并不是按照1:1来划分新生代,一般是按照eden区,s1区,s2区 =8:1:1 来划分
老年代与标记整理算法
因为老年代对象存活率高、没有额外空间对它进行分配担保, 就必须采用“标记—清理”或“标记—整理” 算法来进行回收, 不必进行内存复制, 且直接腾出空闲内存。因而采用 标记整理算法。

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

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

相关文章

Leetcode 用队列实现栈

题目: 请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。 实现 MyStack 类: void push(int x) 将元素 x 压入栈顶。 int pop() 移除并…

【c++笔记】用c++解决一系列质数问题!

质数是c语言和c中比较常见的数学问题,本篇文章将带你走进有关质数的一系列基础问题,其中包含常见的思路总结,本篇文章过后,将会持续更新c算法系列,感兴趣的话麻烦点个关注吧! 希望能给您带来帮助&#xff…

零基础学Python(2)— 安装Python开发工具之PyCharm

前言:Hello大家好,我是小哥谈。PyCharm是由JetBrains公司开发的一款Python开发工具。在Windows、Mac OS和Linux操作系统中都可以使用。它具有语法高亮显示、Project(项目)管理代码跳转、智能提示、自动完成、调试、单元测试和版本…

C++——函数的常见样式

常见的函数样式有4种&#xff0c;即在函数定义过程中函数的四种格式&#xff0c;他们也分别对应了四种调用方法&#xff1a; 1&#xff0c;无参无返 2&#xff0c;有参无返 3&#xff0c;无参有返 4&#xff0c;有参有返 示例&#xff1a; #include<bits/stdc.h> u…

x-cmd pkg | yt-dlp - 专注于 YouTube 的下载工具

目录 简介首次用户功能特点竞品和相关作品进一步探索 简介 yt-dlp 是一款强大的命令行下载工具&#xff0c;专注于下载 YouTube 视频和音频。它是 youtube-dl 的一个改进和拓展版本&#xff0c;提供了更多功能和修复了一些问题。 yt-dlp 具有灵活的支持&#xff0c;可下载 Yo…

武汉灰京文化:手游市场游戏体验和社交互动的新趋势

随着移动设备的普及和技术的不断提高&#xff0c;手游市场正在迎来全新的发展时期。用户的游戏习惯正在发生重大变化&#xff0c;他们越来越倾向于随时随地玩游戏。手游的便携性使得用户可以在公交车上、休息时间或等待朋友时轻松进行游戏。这种随时随地的游戏体验满足了现代生…

【成本价特惠】招募证书代理:工信部、PMP、阿里云、华为等认证,机会难得!

扫码和我联系 亲爱的读者朋友们&#xff0c; 今天&#xff0c;我想和大家分享一个难得的机会。我们目前正在积极招募各类证书的代理&#xff0c;包括工信部的证书、PMP&#xff08;项目管理专业人士&#xff09;证书、阿里云证书、华为证书、OCP 证书、CFA 证书等。这些证书在…

最大流—EK算法,流网络,残留网络,定理证明,详细代码

文章目录 零、卡车运输一、流网络1.1流网络1.2流1.3最大流1.4残留网络1.5增广路径1.6流网络的割1.7最大流最小割定理1.7.1证明 1.8Ford-Fulkerson方法 二、Edmonds-Karp算法2.1定义2.2EK算法的实现2.3EK算法详细代码2.4OJ练习 零、卡车运输 Lucky Puck公司有冰球工厂Vancouver…

Unity导出Android项目踩坑记录

导出的时候需要注意以下地方的配置&#xff1a; 1、buildSetting-> 设置ExportProject 2、buildsetting ->playerSetting ->设置IL2CPP 3、设置ndk edit->preferences->external tools->ndk 如果unity的ndk版本和android项目里的ndk版本不一致会报错&…

【Qt开发】初识Qt

文章目录 1. Qt的背景1.1 Qt是什么1.2 Qt的发展史1.3 Qt支持的平台 2. Qt开发环境的搭建2.1 Qt SDK下载2.2 Qt SDK的安装 3. 一个简单的Qt模板程序的创建4. Qt模板程序的代码讲解4.1 main.cpp4.2 widget.h4.3 widget.cpp4.4 widget.ui4.5 test_1_18.pro4.6 一些中间文件 5. Qt在…

keil软件仿真

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 例如&#xff1a;随着人工智能的不断发展&#xff0c;机器学习这门技术也越来越重要…

vue基于Spring Boot框架的甘肃敦煌文化旅游管理系统

本敦煌文化旅游管理系统是为了提高用户查阅信息的效率和管理人员管理信息的工作效率&#xff0c;可以快速存储大量数据&#xff0c;还有信息检索功能&#xff0c;这大大的满足了用户和管理员这两者的需求。操作简单易懂&#xff0c;合理分析各个模块的功能&#xff0c;尽可能优…

(蓝桥杯每日一题)平方末尾及补充(常用的字符串函数功能)

能够表示为某个整数的平方的数字称为“平方数 虽然无法立即说出某个数是平方数&#xff0c;但经常可以断定某个数不是平方数。因为平方数的末位只可能是:0,1,4,5,6,9 这 6 个数字中的某个。所以&#xff0c;4325435332 必然不是平方数。 如果给你一个 2 位或 2 位以上的数字&am…

六、标准对话框、多应用窗体

一、标准对话框 Qt提供了一些常用的标准对话框&#xff0c;如打开文件对话框、选择颜色对话框、信息提示和确认选择对话框、标准输入对话框等。1、预定义标准对话框 &#xff08;1&#xff09;QFileDialog 文件对话框 QString getOpenFileName() 打开一个文件QstringList ge…

You need to add dependency of ‘poi-ooxml‘ to your project, and version >= 4.1.2

原因 由于在依赖中引用了多个版本的 hutool,导致在最终打包时使用的版本不是由在开发时所引用的版本 cn.hutool.core.exceptions.DependencyException: You need to add dependency of poi-ooxml to your project, and version > 4.1.2at cn.hutool.poi.excel.ExcelUtil.get…

MyBatis-Plus 日常操作

本文主要介绍 mybatis-plus 日常操作。 一、快速开始 本文基于 springboot、maven、jdk1.8、mysql 环境。 新建如下数据库&#xff1a; 建议大家选择 utf8mb4 这种字符集&#xff0c;做过微信的同学应该会知道&#xff0c;微信用户名称的表情&#xff0c;是需要这种字符集才…

基于python旅游推荐系统 协同过滤算法 爬虫 Echarts可视化 Django框架(源码)✅

毕业设计&#xff1a;2023-2024年计算机专业毕业设计选题汇总&#xff08;建议收藏&#xff09; 毕业设计&#xff1a;2023-2024年最新最全计算机专业毕设选题推荐汇总 &#x1f345;感兴趣的可以先收藏起来&#xff0c;点赞、关注不迷路&#xff0c;大家在毕设选题&#xff…

Android14之DefaultKeyedVector实现(一百八十二)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

计算机组成原理 第一弹

ps&#xff1a;本文章的图片来源都是来自于湖科大教书匠高老师的视频&#xff0c;声明&#xff1a;仅供自己复习&#xff0c;里面加上了自己的理解 这里附上视频链接地址&#xff1a;1-2 计算机的发展_哔哩哔哩_bilibili ​​ 目录 &#x1f680;计算机系统 &#x1f680;计…

基于SpringBoot的欢乐校园管理系统

文章目录 项目介绍主要功能截图&#xff1a;部分代码展示设计总结项目获取方式 &#x1f345; 作者主页&#xff1a;超级无敌暴龙战士塔塔开 &#x1f345; 简介&#xff1a;Java领域优质创作者&#x1f3c6;、 简历模板、学习资料、面试题库【关注我&#xff0c;都给你】 &…