面试题:JVM的垃圾回收
一、GC概念
为了让程序员更专注于代码的实现,而不用过多的考虑内存释放的问题,所以,在Java语言中,有了自动的垃圾回收机制,也就是我们熟悉的GC(Garbage Collection)。
有了垃圾回收机制后,程序员只需要关心内存的申请即可,内存的释放由系统自动识别完成。
在进行垃圾回收时,不同的对象引用类型,GC会采用不同的回收时机
换句话说,自动的垃圾回收的算法就会变得非常重要了,如果因为算法的不合理,导致内存资源一直没有释放,同样也可能会导致内存溢出的。
当然,除了Java语言,C#、Python等语言也都有自动的垃圾回收机制。
二、垃圾判定算法
简单一句就是:如果一个或多个对象没有任何的引用指向它了,那么这个对象现
在就是垃圾,如果定位了垃圾,则有可能会被垃圾回收器回收。
如果要定位什么是垃圾,有两种方式来确定:
- 引用计数法
- 可达性分析算法
💖 引用计数法
一个对象被引用了一次,在当前的对象头上递增一次引用次数,如果这个对象的
引用次数为0,代表这个对象可回收
当对象间出现了循环引用的话,则引用计数法就会失效
目前上方的引用关系和计数都是没问题的,但是,如果代码继续往下执行,如下
优点:
- 实时性高,无需等到内存不够的时候,才开始回收,运行时根据对象的计数器是否为 0,就可以直接回收
- 在垃圾回收过程中,应用无需挂起。如果申请内存时,内存不足,则立刻报OOM错误
- 区域性,更新对象的计数器时,只是影响到该对象,不会扫描全部对象。
缺点:
- 每次对象被引用时,都需要去更新计数器,有一点时间开销。
- 浪费 CPU 资源,即使内存任然够用,仍然在运行时进行计数器统计。
- 无法解决循环引用问题,会引发内存泄露。
💖 可达性分析算法
现在的虚拟机采用的都是通过可达性分析算法来确定哪些内容是垃圾。
会存在一个根节点【GC Roots】,引出它下面指向的下一个节点,再以下一个节点节点开始找出它下面的节点,依次往下类推。直到所有的节点全部遍历完毕。
根对象
是那些肯定不能当做垃圾回收的对象
,就可以当做根对象
局部变量,静态方法,静态变量,类信息
核心是:判断某对象是否与根对象有直接或间接的引用,如果没有被引用,则可以当做垃圾回收
X,Y 这两个节点是可回收的,但是并不会马上的被回收!! 对象中存在一个方法【finalize】。当对象被标记为可回收后,当发生GC时,首先会判断这个对象是否执行了finalize方法,如果这个方法还没有被执行的话,那么就会先来执行这个方法,接着在这个方法执行中,可以设置当前这个对象与GC ROOTS产生关联,那么这个方法执行完成之后,GC会再次判断对象是否可达,如果仍然不可达,则会进行回收,如果可达了,则不会进行回收。
finalize方法 对于每一个对象来说,只会执行一次。如果第一次执行这个方法的时候,设置了当前对象与RC ROOTS关联,那么这一次不会进行回收。 那么等到这个对象第二次被标记为可回收时,那么该对象的finalize方法就不会再次执行了。
GC ROOTS:
- 虚拟机栈(栈帧中的本地变量表)中引用的对象
/*** demo是栈帧中的本地变量,当 demo = null 时,由于此时 demo 充当了 GC Root 的作用,demo与原来指向的实例 new Demo() 断开了连接,对象被回收。*/
public class Demo {public static void main(String[] args) {Demo demo = new Demo();demo = null;}
}
- 方法区中类静态属性引用的对象
/*** 当栈帧中的本地变量 b = null 时,由于 b 原来指向的对象与 GC Root (变量 b) 断开了连接,所以 b 原来指向的对象会被回收,而由于我们给 a 赋值了变量的引用,a在此时是类静态属性引用,充当了 GC Root 的作用,它指向的对象依然存活!*/
public class Demo {public static Demo a;public static void main(String[] args) {Demo b = new Demo();b.a = new Demo();b = null;}
}
- 方法区中常量引用的对象
/*** 常量 a 指向的对象并不会因为 demo 指向的对象被回收而回收*/
public class Demo {public static final Demo a = new Demo();public static void main(String[] args) {Demo demo = new Demo();demo = null;}
}
- 本地方法栈中 JNI(即一般说的 Native 方法)引用的对象
三、JVM 垃圾回收算法
1. 标记清除算法
标记清除算法,是将垃圾回收分为2个阶段,分别是标记和清除。
(1)根据可达性分析算法得出的垃圾进行标记
(2)对这些标记为可回收的内容进行垃圾回收
可以看到,标记清除算法解决了引用计数算法中的循环引用的问题,没有从root节点引用的对象都会被回收。
同样,标记清除算法也是有缺点的:
- 效率较低,标记和清除两个动作都需要遍历所有的对象,并且在GC时,需要停止应用程序,对于交互性要求比较高的应用而言这个体验是非常差的。
- (重要)通过标记清除算法清理出来的内存,
碎片化较为严重
,因为被回收的对象可能存在于内存的各个角落,所以清理出来的内存是不连贯的。
2. 复制算法(新生代)
复制算法的核心就是,将原有的内存空间一分为二,每次只用其中的一块,在垃圾回收时,将正在使用的对象复制到另一个内存空间中,然后将该内存空间清空,交换两个内存的角色,完成垃圾的回收。
如果内存中的垃圾对象较多,需要复制的对象就较少,这种情况下适合使用该方式并且效率比较高,反之,则不适合。
(1)将内存区域分成两部分,每次操作其中一个。
(2)当进行垃圾回收时,将正在使用的内存区域中的存活对象移动到未使用的内存区域。当移动完对这部分内存区域一次性清除。
(3)周而复始。
优点:
- 在垃圾对象多的情况下,效率较高
- 清理后,内存无碎片
缺点:
- 分配的2块内存空间,在同一个时刻,只能使用一半,内存使用率较低
3. 标记整理算法
标记整理(压缩)算法是在标记清除算法的基础之上,做了优化改进的算法。和标记清除算法一样,也是从根节点开始,对对象的引用进行标记,在清理阶段,并不是简单的直接清理可回收对象,而是将存活对象都向内存另一端移动,然后清理边界以外的垃圾,从而解决了碎片化的问题。
1)标记垃圾。
2)需要清除向右边走,不需要清除的向左边走。
3)清除边界以外的垃圾。
优缺点同标记清除算法,解决了标记清除算法的碎片化的问题,同时,标记压缩算法多了一步,对象移动内存位置的步骤,其效率也有有一定的影响。
与复制算法对比:复制算法标记完就复制,但标记整理算法得等把所有存活对象都标记完毕,再进行整理
四、分代收集算法
1. 概述
在java8时,堆被分为了两份:新生代和老年代【1:2】,在java7时,还存在一个永久代。
对于新生代,内部又被分为了三个区域。Eden区(伊甸园),S0区(幸存者区0),S1区【8:1:1】
当对新生代产生GC:MinorGC【young GC】
当对老年代代产生GC:Major GC
当对新生代和老年代产生FullGC: 新生代 + 老年代完整垃圾回收,暂停时间长,应尽力避免
2. 工作机制
- 新创建的对象,都会先分配到eden区
-
当伊甸园内存不足,标记伊甸园与 from(现阶段没有)的存活对象
-
将存活对象采用复制算法复制到 to 中,复制完毕后,伊甸园和 from 内存都得到释放
- 经过一段时间后伊甸园的内存又出现不足,标记eden区域to区存活的对象,将存活的对象复制到from区
- 当幸存区对象熬过几次回收(最多15次),晋升到老年代(幸存区内存不足或大对象会导致提前晋升)
MinorGC、 Mixed GC 、 FullGC的区别是什么
-
MinorGC【young GC】发生在新生代的垃圾回收,暂停时间短(STW)
-
Mixed GC 新生代 + 老年代部分区域的垃圾回收,G1 收集器特有
-
FullGC: 新生代 + 老年代完整垃圾回收,暂停时间长(STW),应尽力避免?
名词解释:
STW(Stop-The-World)
:暂停所有应用程序线程,等待垃圾回收的完成
五、JVM 垃圾回收器
在jvm中,实现了多种垃圾收集器,包括:
-
串行垃圾收集器
-
并行垃圾收集器
-
CMS(并发)垃圾收集器
-
G1垃圾收集器
1. 串行垃圾回收器
Serial 和 Serial Old 串行垃圾收集器,是指使用单线程进行垃圾回收,堆内存较小,适合个人电脑
-
Serial 作用于新生代,采用复制算法
-
Serial Old 作用于老年代,采用标记-整理算法
垃圾回收时,只有一个线程在工作,并且java应用中的所有线程都要暂停(STW),等待垃圾回收的完成。
2. 并行垃圾回收器
Parallel New 和 Parallel Old 是一个并行垃圾回收器,JDK8默认使用此垃圾回收器
-
Parallel New 作用于新生代,采用复制算法
-
Parallel Old 作用于老年代,采用标记-整理算法
垃圾回收时,多个线程在工作,并且java应用中的所有线程都要暂停(STW),等待垃圾回收的完成。
3. CMS(并发)垃圾回收器
CMS全称 Concurrent Mark Sweep,是一款并发的、使用标记-清除算法的垃圾回收器,该回收器是针对老年代垃圾回收的,是一款以获取最短回收停顿时间为目标的收集器,停顿时间短,用户体验就好。其最大特点是在进行垃圾回收时,应用仍然能正常运行。
4. G1垃圾回收器 ⭐
① 概述
-
应用于新生代和老年代,在JDK9之后默认使用G1
-
划分成多个区域,每个区域都可以充当 eden,survivor,old, humongous,其中 humongous 专为大对象准备
-
采用复制算法
-
响应时间与吞吐量兼顾
-
分成三个阶段:新生代回收、并发标记、混合收集
-
如果并发失败(即回收速度赶不上创建新对象速度),会触发 Full GC
② Young Collection(年轻代垃圾回收)
-
初始时,所有区域都处于空闲状态
-
创建了一些对象,挑出一些空闲区域作为伊甸园区存储这些对象
-
当伊甸园需要垃圾回收时,挑出一个空闲区域作为幸存区,用复制算法复制存活对象,需要暂停用户线程
-
随着时间流逝,伊甸园的内存又有不足
-
将伊甸园以及之前幸存区中的存活对象,采用复制算法,复制到新的幸存区,其中较老对象晋升至老年代
③ Young Collection + Concurrent Mark (年轻代垃圾回收+并发标记)
当老年代占用内存超过阈值(默认是45%)后,触发并发标记,这时无需暂停用户线程
-
并发标记之后,会有重新标记阶段解决漏标问题,此时需要暂停用户线程。
-
这些都完成后就知道了老年代有哪些存活对象,随后进入混合收集阶段。此时不会对所有老年代区域进行回收,而是根据暂停时间目标优先回收价值高(存活对象少)的区域(这也是 Garbage First 名称的由来)。
④ Mixed Collection (混合垃圾回收)
复制完成,内存得到释放。进入下一轮的新生代回收、并发标记、混合收集
其中H叫做巨型对象,如果对象非常大,会开辟一块连续的空间存储巨型对象
六、强软弱虚引用
💖 强引用
强引用:只有所有 GC Roots 对象都不通过【强引用】引用该对象,该对象才能被垃圾回收
User user = new User();
💖 软引用
软引用:仅有软引用引用该对象时,在垃圾回收后,内存仍不足时会再次触发垃圾回收
User user = new User();
SoftReference softReference = new SoftReference(user);
💖 弱引用
弱引用:仅有弱引用引用该对象时,在垃圾回收时,无论内存是否充足,都会回收弱引用对象
User user = new User();
WeakReference weakReference = new WeakReference(user);
延伸话题:ThreadLocal内存泄漏问题
ThreadLocal用的就是弱引用,看以下源码:
static class Entry extends WeakReference<ThreadLocal<?>> {Object value;Entry(ThreadLocal<?> k, Object v) {super(k);value = v; //强引用,不会被回收}
}
Entry
的 key 是当前 ThreadLocal,value 值是我们要设置的数据。
WeakReference
表示的是弱引用,当JVM进行GC时,一旦发现了只具有弱引用的对象,不管当前内存空间是否足够,都会回收它的内存。但是value
是强引用,它不会被回收掉。
ThreadLocal使用建议:使用完毕后注意调用清理方法。
💖 虚引用
虚引用:必须配合引用队列使用,被引用对象回收时,会将虚引用入队,由 Reference Handler 线程调用虚引用相关方法释放直接内存
相关文章:
面试题:JVM的垃圾回收
一、GC概念 为了让程序员更专注于代码的实现,而不用过多的考虑内存释放的问题,所以,在Java语言中,有了自动的垃圾回收机制,也就是我们熟悉的GC(Garbage Collection)。 有了垃圾回收机制后,程序员只需要关…...
Java8之接口默认方法
Java8之接口默认方法 一、介绍二、代码1、接口2、实现类3、测试代码4、效果 一、介绍 在Java8中,允许为接口方法提供一个默认的实现。必须用default修饰符标记这样一个方法。默认方法也可以调用其他方法 二、代码 1、接口 public interface PersonService {void…...
发挥ChatGPT潜力:高效撰写学术论文技巧
ChatGPT无限次数:点击直达 发挥ChatGPT潜力:高效撰写学术论文技巧 在当今信息爆炸的时代,如何高效撰写学术论文成为许多研究者关注的焦点。而随着人工智能技术的不断发展,如何利用ChatGPT这一先进的技术工具来提升论文写作效率,成…...
国产暴雨AI服务器X3418开启多元自主可控新篇章
在当前数字化转型的大潮中,算力作为新质生产力的重要动力引擎,对推动经济社会发展起着关键作用。尤其在人工智能领域,随着高性能、安全可控的AI算力需求持续攀升,国产化服务器的研发与应用显得尤为迫切。 作为国内专业的算力基础…...
webpack-dev-server 如何直接用IP打开
当你需要使用IP来访问服务器时,可能需要对 webpack-dev-server 进行相关设置; 当你使用PD虚拟机在Windows上调试时,可能会用到; 一、设置 host 通过webpack.config.js设置 devServer: {host: 0.0.0.0, }通过CLI设置 webpack-dev-s…...
Web框架开发-BBS项目预备知识
一、简介 博客系统(cnblog) https://www.cnblogs.com/ 1.django ORM (object relation mapping 对象关系映射) 表 = 类 对象 = 记录跨表查询 分组查询 annotate() 聚合查询 aggregate(*args, **kwargs) 2.bootstrap3.Ajax (jquery javascript) --- javascript 去写…...
力扣208---实现Trie(前缀树)
题目描述: Trie(发音类似 "try")或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补完和拼写检查。 请你实现 Trie 类: …...
书生·浦语大模型开源体系(一)论文精读笔记
💗💗💗欢迎来到我的博客,你将找到有关如何使用技术解决问题的文章,也会找到某个技术的学习路线。无论你是何种职业,我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章,也欢…...
基于单片机模糊算法温度控制系统设计
**单片机设计介绍, 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机模糊算法温度控制系统设计是一个综合性的项目,结合了单片机技术、传感器技术、模糊控制算法等多个方面。以下是对该设计的概要…...
GESP Python编程四级认证真题 2024年3月
Python 四级 2024 年 03 月 1 单选题(每题 2 分,共 30 分) 第 1 题 小杨的父母最近刚刚给他买了一块华为手表,他说手表上跑的是鸿蒙,这个鸿蒙是?( ) A. 小程序 B. 计时器 C. 操作系统…...
Collection与数据结构 顺序表与ArrayList
1. 线性表 线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列… 线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在…...
pytorch | torchvision.transforms.CenterCrop
torchvision.transforms.CenterCrop>从图像中心裁剪图片 transforms.CenterCrop torchvision.transforms.CenterCrop(size) 功能:从图像中心裁剪图片 size: 所需裁剪的图片尺寸 transforms.CenterCrop(196)的效果如下: (也可…...
在Debian 11上安装GCC
GCC(GNU Compiler Collection)是一个功能强大的工具集合,可用于将不同编程语言的源代码编译成可执行文件或库。它支持多种编程语言,包括C、C、Java、Objective-C、Go、Fortran、Ada等。在Debian 11上安装GCC非常简单,以…...
kafka部署之简单密钥
一、说明 centos7.9kafka_2.13-2.7.0.tgzapache-zookeeper-3.8.0-bin.tar.gz官方文档:Apache Kafka 二、kafka配置 2.1、server.properties server.properties修改或增加如下配置 listenersSASL_PLAINTEXT://你的主机ip:9092 super.usersUser:admin authorizer…...
大模型重塑电商,淘宝、百度、京东讲出新故事
配图来自Canva可画 随着AI技术日渐成熟,大模型在各个领域的应用也越来越深入,国内互联网行业也随之进入了大模型竞赛的后半场,开始从“百模大战”转向了实际应用。大模型从通用到细分垂直领域的跨越,也让更多行业迎来了新的商机。…...
用静态工厂方法代替构造器
用静态工厂方法来代替构造方法。 public class Student {private String name;private int age;private String studentId;private Student(String name, int age, String studentId) {this.name name;this.age age;this.studentId studentId;}public static Student creat…...
Discourse 最多允许有几个分类级别
和 DISCUZ 不同,DISCUZ 可以允许分类下面还有分类,再继续分类这种嵌套式分类。 Discourse 最多只允许有 2 个分类。 如果你在已有的分类下再继续分类的话,系统会提示错误: 意思就是子分类不能再分子分类。 Discourse 尽量采取了…...
MySQL数据库主从复制和读写分离
MySQL数据库主从复制和读写分离 。## MySQL主从复制 MySQL主从复制的概念 MySQL主从复制是一个异步的数据复制过程,允许将一个MySQL服务器(主服务器)上的数据复制到一个或多个MySQL服务器(从服务器)。主从复制提供了…...
rust - 使用log4rs打印日志
本文提供了一种通过log4rs库记录日志的方法。这里没有采用读取yaml文件的方式,而是通过对象构造的方式来初始化日志,用于发包时不带配置文件的场景。 初始化日志 在release环境,仅需要将日志打印到文件中,而日常开发时ÿ…...
数据结构:单调栈和单调队列
文章目录 一、单调栈1.1、栈的思想1.2、单调栈1.2.1、单调栈的基本应用:找出数组中每个元素右侧第一个更大的元素1.2.2、单调栈的基本应用:找出数组中每个元素左侧第一个更大的元素1.2.3、单调栈拓展1.2.4、单调栈LeetCode题单 二、单调队列2.1、队列的思…...
大模型RAG性能提升路径
大模型相关目录 大模型,包括部署微调prompt/Agent应用开发、知识库增强、数据库增强、知识图谱增强、自然语言处理、多模态等大模型应用开发内容 从0起步,扬帆起航。 大模型应用向开发路径:AI代理工作流大模型应用开发实用开源项目汇总大模…...
机器视觉学习(九)—— 边缘检测
目录 一、边缘检测 1.1 Canny边缘检测 1.1.1 cv2.Canny函数 1.1.2 Canny边缘检测示例 1.2 角点检测 1.2.1 cv2.goodFeaturesToTrack()函数 1.2.2 OpenCV角点检测示例代码 1.3 直线检测 1.3.1 cv2.HoughLinesP()函数 1.3.2 OpenCV直线检测示例代码 1.4 圆形检测 1.4…...
基于单片机声音分贝采集和显示控制系统设计
**单片机设计介绍,基于单片机声音分贝采集和显示控制系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机声音分贝采集和显示控制系统设计,主要目标是实现声音分贝的实时采集、处理以及显示…...
CentOS使用Docker部署Halo并结合内网穿透实现公网访问本地博客
文章目录 1. Docker部署Halo1.1 检查Docker版本如果未安装Docker可参考已安装Docker步骤:1.2 在Docker中部署Halo 2. Linux安装Cpolar2.1 打开服务器防火墙2.2 安装cpolar内网穿透 3. 配置Halo个人博客公网地址4. 固定Halo公网地址 本文主要介绍如何在CentOS 7系统使…...
打造高效自动化渗透测试系统:关键步骤与实践
随着当前网络安全威胁的不断扩展与升级,开展渗透测试工作已经成为广大企业组织主动识别安全漏洞与潜在风险的关键过程。然而,传统的人工渗透测试模式对测试人员的专业能力和经验水平有很高的要求,企业需要投入较大的时间和资源才能完成。在此…...
绿联 部署vocechat,搭建私人聊天服务器,用于小型团队和家庭环境
1、镜像 privoce/vocechat-server:latest 2、安装 2.1、基础设置 重启策略:容器退出时总是重启容器。 2.2、网络 桥接即可。 2.3、存储空间 装载路径:/home/vocechat-server/data不可变更,权限读写。 2.4、端口设置 容器端口3000不可变…...
考研数学|高效刷透汤家凤《1800》经验分享
当然不需要换老师,如果你在基础阶段连汤老师的课都听不进去,那么换其他老师的话,很大可能也是白搭。 如果你现在对于1800还是一筹莫展的话,那么很明显,这反映出前期基础不扎实,没有真正理解和掌握这部分内…...
LLM推理入门指南②:深入解析KV缓存
在本系列文章《LLM推理入门指南①:文本生成的初始化与解码阶段》中,作者对Transformer解码器的文本生成算法进行了高层次概述,着重介绍了两个阶段:单步初始化阶段,即提示的处理阶段,和逐个生成补全词元的多…...
上采样技术在语义分割中的应用
目录 概要 一、概述 二、实现方法 1.转置卷积 2.反池化 3.双线性插值法 三、在经典网络中的的应用 1.U-Net 2.FCN 总结 概要 上采样是用于深度学习中提高语义分割精度的技术,可以实现图像放大和像素级别标注 一、概述 神经网络的基本结构为:…...
linux 组建raid5详细操作
raid5最多运行损坏一个盘,最少3个盘,容量为少一块硬盘的容量之和。 如果硬盘数量较多,比如8块以上,建议用raid6,raid6最多允许两块硬盘损坏。 如果需要 一、安装raid软件 deb包 apt-get install mdadm或dnf包 dnf …...
wordpress怎么提速/百度秒收录排名软件
这么久没有写博客了,今天给大家分享一些多file文件的操作。一般可以用到清理垃圾获取文件大小 删除文件等操作,可以直接用于工具类里面,直接做操作便可以public final class FileUtils { public static long fileLen 0;public static void d…...
博客群 wordpress/长沙seo就选智优营家
本文讲述在Windows下使用BehaviorTree.CPP,基于VSCode 一 安装CMake和MinGW 请参考这篇文章,确保cmake和MinGW的bin目录添加到系统的环境变量里。 如果安装了Visual Studio,也可以不安装MinGW,只是需要一个编译器而已。本人没有…...
北京视频网站建设/西安网站推广排名
一、打开SecureCRT,打开会话,使用 yum -y install mariadb mariadb-server 命令安装 二、等待安装完毕,显示Complete!,表示安装完毕 三、启动MariaDB服务 service mariadb start 四、设置开机自启动 systemctl enable mariadb 五、…...
网络工作室是什么行业/北京seo分析
文章简介:由浙江卫视和创客星球联合出品、葡萄积木冠名播出的详情>>作者:飞鸟2020-10-28 14:42整理铁甲犀牛多42级后就可以进化了,可以进化为铁详情>>阅读: 8日期: 2020-10-28原标题:铁甲威虫之骑刃王,龙尊…...
WordPress pwa/西安seo外包行者seo06
Spark原理及应用Spark的原理Spark的使用Apache Spark是通用的分布式大数据计算引擎。Spark是UC BerkeleyAMPLab(美国加州大学伯克利分校的AMP实验室)开源的通用并行框架。Spark拥有Hadoop MapReduce所具有的优点,但不同于HadoopMapReduce的是…...
论网站建设情况/百度怎么投放广告
一、基本原理 1.数据源无关的数据统一操作,LINQ语句做了一个程序语句到各种数据源之间的抽象统一中间件。where开始,select或group结束. order 和group,select new等各种语句 。 2.用了拓展方法,在generic枚举类型来做࿰…...