面试阿里,这篇JVM垃圾回收算法就够了(下)

简介: 面试阿里,这篇JVM垃圾回收算法就够了(下)

4 GC算法

知道了如何判定:

  • 一个对象是无效对象
  • 一个类是无用类
  • 一个常量是废弃常量

也就知道了垃圾收集器会清除哪些数据,那么它们是如何清除这些数据的呢?

4.1 标记-清除算法(Mark-Sweep)

最基础的收集算法,因为后续算法也都是基于该思路,对其不足之处进行优化而得。

  • 首先判断需要清除哪些数据,并给它们做上标记
  • 然后清除被标记的数据

缺陷

标记和清除过程效率都不高,且标记清除之后存在大量内存碎片,降低了空间利用率这会导致日后因为存储大对象时无法找到足够连续内存而提前触发GC。

image.png

4.2 复制算法(Copying)

  • 将内存分成大小相等两份,只将数据存储在其中一块上.当需要回收时,也是首先标记出废弃的数据,然后将有用的数据复制到另一块内存上,最后将第一块内存全部清除.
  • image.png
  • 分析

这种算法避免了空间碎片,但内存缩小了一半.

而且每次都需要将有用的数据全部复制到另一片内存上去,效率不高.


解决空间利用率问题

在新生代中,由于大量的对象都是"朝生夕死",也就是一次垃圾收集后只有少量对象存活,因此我们可以将内存划分成三块:Eden、Survior1、Survior2,内存大小分别是8:1:1.分配内存时,只使用Eden和一块Survior1.当发现Eden+Survior1的内存即将满时,JVM会发起一次MinorGC,清除掉废弃的对象,并将所有存活下来的对象复制到另一块Survior2中.接下来就使用Survior2+Eden进行内存分配.

通过这种方式,只需要浪费10%的内存空间即可实现带有压缩功能的垃圾收集方法,避免了内存碎片的问题.


什么是分配担保?

当JVM准备为一个对象分配内存空间时,发现此时Eden+Survior中空闲的区域无法装下该对象,那么就会触发MinorGC,对该区域的废弃对象进行回收.但如果MinorGC过后只有少量对象被回收,仍然无法装下新对象,那么此时需要将Eden+Survior中的所有对象都转移到老年代中,然后再将新对象存入Eden区.这个过程就是"分配担保".

4.3 标记-整理算法(Mark-Compact)

效率偏低。

GC前的标记过程仍与"标记-清除"一样,但后续不是直接清理可回收对象,而是将所有存活的对象移到一端,然后直接清掉端边界之外的内存。

image.png

分析

一种老年代GC算法,老年代中的对象一般寿命较长,因此每次GC后会有大量对象存活,所以若选用"复制"算法,则每次需要很多的复制操作,效率很低。

在新生代中使用"复制"算法,当Eden+Survior中都装不下某对象时,可使用老年代的内存进行"分配担保"。而若在老年代使用“复制”算法,若老年代出现Eden+Survior装不下某个对象时,没有其他区域给它作分配担保。因此,老年代中一般使用"标记-整理"算法。

4.4 分代收集算法(Generational Collection)

当前商业虚拟机都采用此算法.根据对象存活周期的不同将Java堆划分为老年代和新生代,根据各个年代的特点使用最佳的收集算法.

  • 老年代中对象存活率高,无额外空间对其分配担保,必须使用"标记-清理"或"标记-整理"算法;
  • 新生代中存放"朝生夕死"的对象那就用复制算法,只需要付出少量存活对象的复制成本就可以完成收集.

5 Java中引用的种类

Java中根据生命周期的长短,将引用分为4类


强引用

我们平时所使用的引用就是强引用.

类似A a = new A();

也就是通过关键字new创建的对象所关联的引用就是强引用.

只要强引用还存在,该对象永远不会被回收.


软引用

一些还有用但并非必需的对象

只有当堆即将发生OOM异常时,JVM才会回收软引用所指向的对象.

软引用通过SoftReference类实现.

软引用的生命周期比强引用短一些.


弱引用

也是描述非必需对象,比软引用更弱

所关联的对象只能存活到下一次GC发生前.

只要垃圾收集器工作,无论内存是否足够,弱引用所关联的对象都会被回收.

弱引用通过WeakReference类实现.


虚引用

也叫幽灵(幻影)引用,最弱的引用关系.

它和没有引用没有区别,无法通过虚引用取得对象实例.

设置虚引用唯一的作用就是在该对象被回收之前收到一条系统通知.

虚引用通过PhantomReference类来实现.


目录
相关文章
|
算法
面试场景题:如何设计一个抢红包随机算法
本文详细解析了抢红包随机算法的设计与实现,涵盖三种解法:随机分配法、二倍均值法和线段切割法。随机分配法通过逐次随机分配金额确保总额不变,但易导致两极分化;二倍均值法优化了金额分布,使每次抢到的金额更均衡;线段切割法则将总金额视为线段,通过随机切割点生成子金额,手气最佳金额可能更高。代码示例清晰,结果对比直观,为面试中类似算法题提供了全面思路。
2021 16
|
算法 安全 Java
Java线程调度揭秘:从算法到策略,让你面试稳赢!
在社招面试中,关于线程调度和同步的相关问题常常让人感到棘手。今天,我们将深入解析Java中的线程调度算法、调度策略,探讨线程调度器、时间分片的工作原理,并带你了解常见的线程同步方法。让我们一起破解这些面试难题,提升你的Java并发编程技能!
649 16
|
SQL 缓存 监控
大厂面试高频:4 大性能优化策略(数据库、SQL、JVM等)
本文详细解析了数据库、缓存、异步处理和Web性能优化四大策略,系统性能优化必知必备,大厂面试高频。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:4 大性能优化策略(数据库、SQL、JVM等)
|
存储 监控 算法
Java JVM 面试题
Java JVM(虚拟机)相关基础面试题
382 4
|
存储 算法 安全
JVM常见面试题(四):垃圾回收
堆区域划分,对象什么时候可以被垃圾器回收,如何定位垃圾——引用计数法、可达性分析算法,JVM垃圾回收算法——标记清除算法、标记整理算法、复制算法、分代回收算法;JVM垃圾回收器——串行、并行、CMS垃圾回收器、G1垃圾回收器;强引用、软引用、弱引用、虚引用
|
Arthas 监控 Java
JVM进阶调优系列(9)大厂面试官:内存溢出几种?能否现场演示一下?| 面试就那点事
本文介绍了JVM内存溢出(OOM)的四种类型:堆内存、栈内存、元数据区和直接内存溢出。每种类型通过示例代码演示了如何触发OOM,并分析了其原因。文章还提供了如何使用JVM命令工具(如jmap、jhat、GCeasy、Arthas等)分析和定位内存溢出问题的方法。最后,强调了合理设置JVM参数和及时回收内存的重要性。
|
机器学习/深度学习 算法 Java
机器学习、基础算法、python常见面试题必知必答系列大全:(面试问题持续更新)
机器学习、基础算法、python常见面试题必知必答系列大全:(面试问题持续更新)
|
算法 Java 数据库
美团面试:百亿级分片,如何设计基因算法?
40岁老架构师尼恩在读者群中分享了关于分库分表的基因算法设计,旨在帮助大家应对一线互联网企业的面试题。文章详细介绍了分库分表的背景、分片键的设计目标和建议,以及基因法的具体应用和优缺点。通过系统化的梳理,帮助读者提升架构、设计和开发水平,顺利通过面试。
美团面试:百亿级分片,如何设计基因算法?
|
算法 Java
JVM有哪些垃圾回收算法?
(1)标记清除算法: 标记不需要回收的对象,然后清除没有标记的对象,会造成许多内存碎片。 (2)复制算法: 将内存分为两块,只使用一块,进行垃圾回收时,先将存活的对象复制到另一块区域,然后清空之前的区域。用在新生代 (3)标记整理算法: 与标记清除算法类似,但是在标记之后,将存活对象向一端移动,然后清除边界外的垃圾对象。用在老年代
205 0
|
算法 JavaScript 前端开发
垃圾回收算法的原理
【10月更文挑战第13天】垃圾回收算法的原理
301 0