经典面试题:聊一聊垃圾回收算法

简介: 关于垃圾回收算法的这道面试题,几乎是所有 3 年以上的 Java 面试中必问的题目,甚至有些好一点的公司会在校招时问到面试者。那么本文就系统的讲一下垃圾回收的算法,和 Hotspot 虚拟机执行垃圾回收的一些实现细节,比如安全点和安全区域等。

因为各个平台的虚拟机操作内存的方法各不相同,且牵扯大量的程序实现细节,所以本文不会过多的讨论算法的具体实现,只会介绍几种算法思想及发展过程。


垃圾回收算法


1、标记-清除算法


标记-清除算法是最基础的算法,像它的名字一样算法分为“标记”和“清除”两个阶段,首先需要标记出所需要回收的对象,标记完成后统一收集被标记的对象。


优点: 实现简单。

缺点: 产生不连续的内存碎片;“标记”和“清除”的执行效率都不高。


标记-清除算法执行过程图:


微信图片_20220117174204.jpg


(本文图片来自《深入理解Java虚拟机》)


2、复制算法


复制算法就是将内存分为大小相同的两块,当这一块使用完了,就把当前存活的对象复制到另一块,然后一次性清空当前区块。


优点: 执行效率高。

缺点: 空间利用率低, 因为复制算法每次只能使用一半的内存。


微信图片_20220117174206.jpg


3、标记-整理算法


也称标记-压缩算法,标记-整理算法采用和标记清除算法一样的对象“标记”,但后续不会对可回收对象进行清理,而是将存活的对象往一端空闲空间移动,然后清理边界以外的内存空间。


优点: 解决了内存碎片问题,比复制算法空间利用率高。

缺点: 因为有局部对象移动,相对效率不高。


标记-整理算法执行过程图:


微信图片_20220117174209.jpg


4、分代收集算法


目前商用虚拟机都采用的是分代收集的算法,这种算法按照对象存活周期把内存分为几块,一般Java中分为新生代和老年代。把存活率低的对象分到新生代使用复制算法提高垃圾回收的性能,老年代则存放存活率搞的对象,使用标记-清除和标记-整理的算法,提高内存空间使用率。


新生代和老生代的具体介绍和参数配置,后续的文章会详细讲解。


垃圾回收执行细节


本节将详细的介绍一下HotSpot虚拟机在执行垃圾回收时的一些细节,目的是让读者更好的理解Java虚拟机。


HotSpot虚拟机: 它是Sun JDK和OpenJDK自定的虚拟机,也是目前使用最广泛的虚拟机。


垃圾回收流程: Java虚拟机在内存回收之前,为了保证内存的一致性,必须先暂停程序的执行,也就是传说中的Stop The World(简称STW),在使用可达性分析算法枚举GC Roots,标记出死亡对象,再进行垃圾回收。


垃圾回收遇到的问题: 那既然是要暂停程序的运行,就一定要保证停止的时间足够短,并且可控,不然带来的灾难将是毁灭性的。


解决方案: 显然HotSpot在设计的时候也考虑到了这个问题,所以在JIT编译的时候就会使用OopMap数据结构来记录栈和寄存器上的引用,这样虚拟机就直接知道了那些地方存放着对象的引用,如下图,为我编译String.hashCode()方法的部分本地代码:


微信图片_20220117174211.png


可以看出,使用OopMap数据结构存储了普通对象的指针引用。


查看汇编的方法,启动命令窗体执行:

java-XX:+UnlockDiagnosticVMOptions-XX:+PrintAssemblyYouTestClass


命令可能会报错:

Couldnotload hsdis-amd64.dll;librarynotloadable;PrintAssemblyisdisabled

报错解决方法:使用编译好的hsdis.dll放到:jre安装目录\bin\server目录下即可,hsdis.dll地址地址:https://pan.baidu.com/s/1-D6u0gnUx291LXS3bHOorA


安全点(Safepoint)


在OopMap的协助下,HotSpot可以快速的完成GC Roots枚举,但导致OopMap内容变化的指令很多,而且如果给每个对象生成对应的OopMap,会造成大量额外的空间,这会导致GC成本很高,所以HotSpot只会在“特定的位置”生成对应的OopMap,这些位置就成为“安全点”。


HotSpot也并不是任何时刻都会停顿下来进行GC,只会在程序都到底安全点之后才会GC,所以安全点的设置不能太少,让GC等待时间太长,也不能太多增大运行时的成本。


安全点的两种线程中断方式


抢断式中断:不需要线程的执行代码去主动配合,当发生GC时,先强制中断所有线程,然后如果发现某些线程未处于安全点,恢复程序运行,直到进入安全点为止。


主动式中断:不强制中断线程,只是简单地设置一个中断标记,各个线程在执行时轮询这个标记,一旦发现标记被改变(出现中断标记)时,那么将运行到安全点后自己中断挂起。目前所有商用虚拟机全部采用主动式中断。


安全区域(Saferegion)


安全点机制仅仅是保证了程序执行时不需要太长时间就可以进入一个安全点进行 GC 动作,但是当特殊情况时,比如线程休眠、线程阻塞等状态的情况下,显然HotSpot不可能一直等待被阻塞或休眠的线程正常唤醒执行;此时就引入了安全区的概念。


安全区(Saferegion):安全区域是指在一段区域内,对象引用关系等不会发生变化,在此区域内任意位置开始GC都是安全的;线程运行时,首先标记自己进入了安全区,然后在这段区域内,如果线程发生了阻塞、休眠等操作,HotSpot发起GC时将忽略这些处于安全区的线程。当线程再次被唤醒时,首先他会检查是否完成了GC Roots枚举(或这个GC过程),如果完成了就继续执行,否则将继续等待直到收到可以安全离开的Safe Region的信号为止。


总结


前面讲的垃圾回收器算法属于基本功,要求面试者一定要熟练记忆的,而后面的垃圾收集器的执行细节如果加分项,如果都能融会贯通的话,Offer 就离你又进一步了。


相关文章
|
7月前
|
算法
面试场景题:如何设计一个抢红包随机算法
本文详细解析了抢红包随机算法的设计与实现,涵盖三种解法:随机分配法、二倍均值法和线段切割法。随机分配法通过逐次随机分配金额确保总额不变,但易导致两极分化;二倍均值法优化了金额分布,使每次抢到的金额更均衡;线段切割法则将总金额视为线段,通过随机切割点生成子金额,手气最佳金额可能更高。代码示例清晰,结果对比直观,为面试中类似算法题提供了全面思路。
1224 16
|
9月前
|
算法 安全 Java
Java线程调度揭秘:从算法到策略,让你面试稳赢!
在社招面试中,关于线程调度和同步的相关问题常常让人感到棘手。今天,我们将深入解析Java中的线程调度算法、调度策略,探讨线程调度器、时间分片的工作原理,并带你了解常见的线程同步方法。让我们一起破解这些面试难题,提升你的Java并发编程技能!
284 16
|
11月前
|
存储 算法 安全
JVM常见面试题(四):垃圾回收
堆区域划分,对象什么时候可以被垃圾器回收,如何定位垃圾——引用计数法、可达性分析算法,JVM垃圾回收算法——标记清除算法、标记整理算法、复制算法、分代回收算法;JVM垃圾回收器——串行、并行、CMS垃圾回收器、G1垃圾回收器;强引用、软引用、弱引用、虚引用
|
12月前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
546 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
12月前
|
算法 Java 数据库
美团面试:百亿级分片,如何设计基因算法?
40岁老架构师尼恩分享分库分表的基因算法设计,涵盖分片键选择、水平拆分策略及基因法优化查询效率等内容,助力面试者应对大厂技术面试,提高架构设计能力。
美团面试:百亿级分片,如何设计基因算法?
|
12月前
|
存储 监控 算法
美团面试:说说 G1垃圾回收 底层原理?说说你 JVM 调优的过程 ?
尼恩提示: G1垃圾回收 原理非常重要, 是面试的重点, 大家一定要好好掌握
美团面试:说说 G1垃圾回收 底层原理?说说你 JVM 调优的过程  ?
|
12月前
|
算法 前端开发 Java
数据结构与算法学习四:单链表面试题,新浪、腾讯【有难度】、百度面试题
这篇文章总结了单链表的常见面试题,并提供了详细的问题分析、思路分析以及Java代码实现,包括求单链表中有效节点的个数、查找单链表中的倒数第k个节点、单链表的反转以及从尾到头打印单链表等题目。
132 1
数据结构与算法学习四:单链表面试题,新浪、腾讯【有难度】、百度面试题
|
12月前
|
机器学习/深度学习 算法 Java
机器学习、基础算法、python常见面试题必知必答系列大全:(面试问题持续更新)
机器学习、基础算法、python常见面试题必知必答系列大全:(面试问题持续更新)
|
12月前
|
算法 Java 数据库
美团面试:百亿级分片,如何设计基因算法?
40岁老架构师尼恩在读者群中分享了关于分库分表的基因算法设计,旨在帮助大家应对一线互联网企业的面试题。文章详细介绍了分库分表的背景、分片键的设计目标和建议,以及基因法的具体应用和优缺点。通过系统化的梳理,帮助读者提升架构、设计和开发水平,顺利通过面试。
美团面试:百亿级分片,如何设计基因算法?
|
11月前
|
算法 Java
JVM有哪些垃圾回收算法?
(1)标记清除算法: 标记不需要回收的对象,然后清除没有标记的对象,会造成许多内存碎片。 (2)复制算法: 将内存分为两块,只使用一块,进行垃圾回收时,先将存活的对象复制到另一块区域,然后清空之前的区域。用在新生代 (3)标记整理算法: 与标记清除算法类似,但是在标记之后,将存活对象向一端移动,然后清除边界外的垃圾对象。用在老年代
113 0

热门文章

最新文章