面试笔记——垃圾回收

对象被垃圾回收的时机

垃圾回收主要面向的是堆中的对象。简单一句就是:如果一个或多个对象没有任何的引用指向它了,那么这个对象现在就是垃圾,如果定位了垃圾,则有可能会被垃圾回收器回收。
如果要定位什么是垃圾,有两种方式来确定,第一个是引用计数法,第二个是可达性分析算法

引用计数法: 一个对象被引用了一次,在当前的对象头上递增一次引用次数,如果这个对象的引用次数为0,代表这个对象可回收,如图:
在这里插入图片描述
但是,当对象间出现了循环引用的话,引用计数就会失效,如图——当运行完红色框中的代码时,a,b的引用值为2:
在这里插入图片描述
当将a,b设置为null后,栈中的变量a,b不再引用堆中的两个内存,此时对象a,b的引用数量为1(因为对象之间存在循环引用):
在这里插入图片描述
此时,堆中的对象a,b不会再被使用,但由于引用数量不为0,也不会被回收,从而引发内存泄漏。

可达性分析算法
可达性分析算法是指扫描堆中的对象,看是否能够沿着 GC Root 对象 为起点的引用链找到该对象,找不到,表示可以回收。
如图,X,Y这两个节点是可回收的(它们没有和GC Root相关联):
在这里插入图片描述
现在的虚拟机采用的都是通过可达性分析算法来确定哪些内容是垃圾。
可以作为GC Root的对象:

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中 JNI(即一般说的 Native 方法)引用的对象

JVM垃圾回收算法

垃圾回收算法:

  • 标记清除算法
  • 复制算法
  • 标记整理算法

标记清除算法
标记清除算法,是将垃圾回收分为2个阶段,分别是标记和清除。

  1. 根据可达性分析算法得出的垃圾进行标记
  2. 对这些标记为可回收的内容进行垃圾回收

如图:
在这里插入图片描述
优点:标记和清除速度较快
缺点:碎片化较为严重,内存不连贯的

标记整理算法 标记清除算法一样,将存活对象都向内存另一端移动,然后清理边界以外的垃圾,无碎片,对象需要移动,效率低。
在这里插入图片描述
解决了标记清除算法的碎片化的问题,同时,标记压缩算法多了一步,对象移动内存位置的步骤,其效率也有有一定的影响。

复制算法 将原有的内存空间一分为二,每次只用其中的一块,正在使用的对象复制到另一个内存空间中,然后将该内存空间清空,交换两个内存的角色,完成垃圾的回收;无碎片,内存使用率低。
在这里插入图片描述
优点:

  • 在垃圾对象多的情况下,效率较高
  • 清理后,内存无碎片

缺点:分配的2块内存空间,在同一个时刻,只能使用一半,内存使用率较低。

JVM的分代回收

在java8时,堆被分为了两份:新生代和老年代【1:2】,如图:
在这里插入图片描述

对于新生代,内部又被分为了三个区域:

  • 伊甸园区Eden,新生的对象都分配到这里
  • 幸存者区survivor(分成from和to, from和to是相对状态)
  • Eden区,from区,to区【8:1:1】

分代回收算法-工作机制:

  1. 新创建的对象,都会先分配到eden区
  2. 当伊甸园内存不足,标记伊甸园与 from(现阶段没有)的存活对象
  3. 将存活对象采用复制算法复制到to中,复制完毕后,伊甸园和 from 内存都得到释放
  4. 经过一段时间后伊甸园的内存又出现不足,标记eden区域to区存活的对象,将其复制到from区
  5. 当幸存区对象熬过几次回收(最多15次),晋升到老年代(幸存区内存不足或大对象会提前晋升)

如图,假设在Eden区被划分完后的状态如下图所示:
在这里插入图片描述
此时,伊甸园内存不足,标记伊甸园和from区的存活对象(对象A);将存活对象采用复制算法复制到 to 中,复制完毕后,伊甸园和 from 内存都得到释放,同时from和to发生交换,如下图:
在这里插入图片描述
如果,伊甸园再次内存不足:
在这里插入图片描述
重复操作2,3后,此时的内存状态为(复制到to之后,from和to发生交换):
在这里插入图片描述
随后,再次发生内存不足:
在这里插入图片描述
当幸存区对象熬过几次回收(最多15次),晋升到老年代(幸存区内存不足或大对象会导致提前晋升):
在这里插入图片描述

ps:在看上面的过程的时候,可能对from和to的相关操作有些疑惑(一会儿的是to一会儿又是from的),其实他们只是一个名字而已,实际就是两块内存,我们可以认为,在进行扫描时,内存中带有数据的为from,即将把数据复制到对应的内存为to。

MinorGC、 Mixed GC 、 FullGC的区别:

  • MinorGC【young GC】发生在新生代的垃圾回收,暂停时间短(STW)
  • Mixed GC 新生代 + 老年代部分区域的垃圾回收,G1 收集器特有
  • FullGC: 新生代 + 老年代完整垃圾回收(新生代和老年代内存严重不足时),暂停时间长(STW),应尽力避免

STW(Stop-The-World):暂停所有应用程序线程,等待垃圾回收的完成。

JVM的垃圾回收器

在jvm中,实现了多种垃圾收集器,包括:

  • 串行垃圾收集器
  • 并行垃圾收集器
  • CMS(并发)垃圾收集器
  • G1垃圾收集器

串行垃圾收集器
Serial和Serial Old串行垃圾收集器,是指使用单线程进行垃圾回收,堆内存较小,适合个人电脑

  • Serial 作用于新生代,采用复制算法
  • Serial Old 作用于老年代,采用标记-整理算法

垃圾回收时,只有一个线程在工作,并且java应用中的所有线程都要暂停(STW),等待垃圾回收的完成。

在这里插入图片描述

并行垃圾收集器
Parallel New和Parallel Old是一个并行垃圾回收器,JDK8默认使用此垃圾回收器

  • Parallel New作用于新生代,采用复制算法
  • Parallel Old作用于老年代,采用标记-整理算法

垃圾回收时,多个线程在工作,并且java应用中的所有线程都要暂停(STW),等待垃圾回收的完成。
在这里插入图片描述

CMS(并发)垃圾收集器
CMS全称 Concurrent Mark Sweep,是一款并发的、使用标记-清除算法的垃圾回收器,该回收器是针对老年代垃圾回收的,是一款以获取最短回收停顿时间为目标的收集器,停顿时间短,用户体验就好。其最大特点是在进行垃圾回收时,应用仍然能正常运行。
在这里插入图片描述
初始标记——标记跟GC Root直接关联的对象;
并发标记——追踪引用链,探索与初始标记后的对象相关联的对象;
重新标记——由于在并发标记阶段,其它线程是可以继续执行的,所以可能出现新的引用或减少了引用,所以需要重新标记。

举例:
在这里插入图片描述
在上图中,各个标记阶段的标记对象为:

  • 初始阶段:对象A
  • 并发标记:对象B,C,D
    若在并发阶段A指向的对象X:
    在这里插入图片描述
    因此,重新标记阶段:对象C。
G1垃圾回收器
  • 应用于新生代和老年代,在JDK9之后默认使用G1
  • 划分成多个区域,每个区域都可以充当 eden,survivor,old, humongous,其中 humongous 专为大对象准备
  • 采用复制算法
  • 响应时间与吞吐量兼顾
  • 分成三个阶段:新生代回收、并发标记、混合收集
  • 如果并发失败(即回收速度赶不上创建新对象速度),会触发 Full GC

G1的三个阶段:
在这里插入图片描述
Young Collection(年轻代垃圾回收)

  • 初始时,所有区域都处于空闲状态
    在这里插入图片描述

  • 创建了一些对象,挑出一些空闲区域作为伊甸园区存储这些对象
    在这里插入图片描述

  • 当伊甸园需要垃圾回收时,挑出一个空闲区域作为幸存区,用复制算法复制存活对象,需要暂停用户线程
    在这里插入图片描述
    在这里插入图片描述

  • 随着时间流逝,伊甸园的内存又有不足
    在这里插入图片描述

  • 将伊甸园以及之前幸存区中的存活对象,采用复制算法,复制到新的幸存区,其中较老对象晋升至老年代
    在这里插入图片描述
    在这里插入图片描述

并发的标记阶段

  • 当老年代占用内存超过阈值(默认是45%)后,触发并发标记,这时无需暂停用户线程。
    在这里插入图片描述
  • 并发标记之后,会有重新标记阶段解决漏标问题,此时需要暂停用户线程。
  • 这些都完成后就知道了老年代有哪些存活对象,随后进入混合收集阶段。此时不会对所有老年代区域进行回收,而是根据暂停时间目标优先回收价值高(存活对象少)的区域(这也是 Gabage First 名称的由来):
    在这里插入图片描述

混合收集

  • 混合收集阶段中,参与复制的有 eden、survivor、old
    在这里插入图片描述
  • 复制完成,内存得到释放。进入下一轮的新生代回收、并发标记、混合收集
    在这里插入图片描述

针对一个很大的对象,此时会将该对象存储到humongous中,如果一个区域装不下,会分配一个连续的区域来存储巨型对象:
在这里插入图片描述

强引用、软引用、弱引用、虚引用的区别

强引用:只有所有 GC Roots 对象都不通过【强引用】引用该对象,该对象才能被垃圾回收。
在这里插入图片描述

软引用:仅有软引用引用该对象时,在垃圾回收后,内存仍不足时会再次触发垃圾回收。在这里插入图片描述
弱引用:仅有弱引用引用该对象时,在垃圾回收时,无论内存是否充足,都会回收弱引用对象。
在这里插入图片描述
dd
虚引用:必须配合引用队列使用,被引用对象回收时,会将虚引用入队,由 Reference Handler 线程调用虚引用相关方法释放直接内存。
在这里插入图片描述

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

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

相关文章

分布式锁-快速入门

文章目录 前言一、基础概念1.1 什么是锁1.2 什么是分布式锁1.3 锁和事务的区别二、分布式锁基础理论2.1 为什么要使用分布式锁2.2 分布式锁特性2.3 分布式锁的实现方式总结前言 由于在平时的工作中,线上服务器是分布式多台部署的,经常会面临解决分布式场景下数据一致性的问题…

TRILL解析

Deep Imitation Learning for Humanoid Loco-manipulation through Human Teleoperation解析 摘要1.简介2. Related work2.1 人形机器人的局部操纵2.2 远程操作示范中的模仿学习 3. 方法 论文链接:https://arxiv.org/abs/2309.01952 论文项目:https://ut…

通过mask得到bbox(numpy实现)

在SAM的加持下,我们很容易得到物体的mask,但是物体的bbox信息通常也很有用。那么,我们可以写一个函数,立马可以通过mask得到bbox。 代码如下: import numpy as npdef mask2bbox(mask):nonzero_indices np.nonzero(m…

运维开发工程师教程之MongoDB单机版设置

MongoDB单机版设置 一、创建虚拟机 在VMware Workstation软件中新建一个虚拟机,具体操作步骤如下: ①运行VMware Workstation软件,进入到主界面,单击“创建新的虚拟机”来创建新的虚拟机,如图3-1所示。 图3-1 VMware…

Anaconda安装教程

1Anaconda 简介 Anaconda是一个数据科学平台,提供一个发行版的 Python 以及大量常用的数据科学包、库和工具。通过包含诸如 NumPy、Pandas、SciPy、Matplotlib等核心库,以及 Jupyter Notebook等开发工具,使数据分析、机器学习和数据可视化变…

stm32和树莓派的区别?

在开始前我有一些资料,是我根据网友给的问题精心整理了一份「stm32的资料从专业入门到高级教程」, 点个关注在评论区回复“888”之后私信回复“888”,全部无偿共享给大家!!!Stm32和树莓派是两个不同的领域…

百度副总裁秒批离职,00后的职场逆袭?

“员工闹分手提离职我秒批”,百度副总裁璩静的职场经历和思考在近期引发了大量讨论。 璩静在小红书分享了自己作为女性管理者,面对团队内部的感情问题,是如何处理的: “我第一时间就跟这个年轻的女孩子说,你走吧&…

18、ESP32 ESP-NOW 点对点通信

ESP-NOW 是乐鑫自主研发的无连接通信协议,具有短数据包传输功能。该协议使多个设备能够以简单的方式相互通信。 ESP-NOW 功能 ESP-NOW 支持以下功能: 加密和未加密的单播通信;混合加密和未加密的对等设备;最多可携带 250 字节 的有效载荷;发送回调功能…

【EasySpider】EasySpider+mysql执行配置异常

问题 使用易采集工具操作时候,遇到一个执行异常,后来发现没有选择数据类型 Loading stealth.min.js MySQL config file path: ./mysql_config.json 成功连接到数据库。 Successfully connected to the database. Traceback (most recent call last):…

如何练英语口语?三个简单练习方法

如何练英语口语?在全球化日益加速的今天,英语已经成为了一种必不可少的交流工具。对于很多人来说,尤其是那些想要在国际舞台上崭露头角的人,流利的英语口语更是必不可少的技能。但是,很多人也面临着一个问题&#xff1…

【Flutter】App内购支付集成 Google和Apple支付和服务器验证全流程

Flutter支付集成 前言: 以谷歌内购为例,我们需要做的总共为三步 需要在谷歌市场配置商品,设置测试渠道,配置开发者账号,设置对应权限。配置完商品之后,如何在 Flutter 中获取到商品,购买指定…

Unity技术学习:渲染大量物体的解决方案,外加RenderMesh、RenderMeshInstanced、RenderMeshIndirect的简单使用

叠甲:本人比较菜,如果哪里不对或者有认知不到的地方,欢迎锐评(不玻璃心)! 导师留了个任务,渲染大量的、移动的物体。 寻找解决方案: 当时找了几个解决方案: 静态批处…

面试集中营—JVM篇

一、JVM内存模型 线程独占:栈,本地方法栈,程序计数器; 线程共享:堆,方法区 虚拟机栈:线程私有的,线程执行方法是会创建一个栈阵,用来存储局部变量表,操作栈,…

多个开源的js补环境框架测试

原文链接:https://mp.weixin.qq.com/s/uEMFGpE5bqmTvzSgX2twvA 前言 在做js逆向时肯定会遇到补环境的情况,看到github开源了好几个补环境用的框架,这篇文章做个测试,看看哪个比较好用。 https://github.com/pysunday/sdenvhttp…

python直接发布到网站wordpress之三批量发布图片

在前面的文章中,实现了使用python操作wordpress发布文字内容和图片内容。 python直接发布到网站wordpress之一只发布文字-CSDN博客 python直接发布到网站wordpress之二发布图片-CSDN博客 不过,此时发布图片的数量只能是一张图片。但在实际应用中&…

电脑桌面备忘录在哪里设置?好用的电脑桌面备忘录软件

在日常工作和生活中,电脑桌面备忘录的重要性不言而喻。想象一下,在繁忙的工作中,你能够一眼看到桌面上的备忘录提醒,从而及时完成重要任务,或者在紧张的学习中,通过备忘录快速回顾关键知识点。一款优秀的电…

HIVE函数的基本使用

HIVE函数的基本使用 1.查看所有支持的函数 共289个 1)SHOW FUNCTIONS 查看所有支持的函数 共289个 2)SHOW FUNCTIONS LIKE "**" 模糊查询函数名 3)DESC FUNCTION 函数名 可以查看函数的具体使用方法 show functions; show functions like "*c…

IDEA中git的常用操作(保姆级教学)

IDEA中git的常用操作(保姆级教学) 以下是git的工作原理,觉得繁琐的可以跳过不看 Workspace:工作区 (平时存放代码的地方) Index / Stage:暂存区(用于临时存放存放你的改动,事实上就是一个文件&…

华人团队用大模型实现“读心术”:大脑活动直接变文字

NeurIPS收录的一项新研究,让大模型也学会“读心术”了! 通过学习脑电波数据,模型成功地把受试者的脑电图信号翻译成了文本。 而且整个过程不需要大型设备,只要一块特制的“头巾”就能实现。 这项成果名为DeWave,能在…

C语言趣味代码(五)

我想以此篇结束关于C语言的博客,因为在C语言拖得越久越不能给大家带来新的创作,在此我也相信大家对C语言已经有了一个新的认知。进入正题,在这一篇中我主要编一个“英语单词练习小程序”来给大家展开介绍,从测试版逐步改良&#x…