Java教程

面试官!垃圾回收千万别问我

本文主要是介绍面试官!垃圾回收千万别问我,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

前言

今天初步来了解一下有关于垃圾回收的基本入门知识,听大佬们说这些都是皮毛,可是还是花了挺多时间来理解这几个知识点

  • 具体如何来判断对象是否存活?

  • 强、软、弱、虚引用到底是些啥?

  • 垃圾回收算法有哪几种?

  • 分代模型又是什么?

1、判断对象是否存活的两种方式

引用计数法

在对象中添加一个引用计数器,每当有一个地方引用就加1,有一个地方引用失效就减1,任何时刻计数器为0的对象都是不可能再使用的。

优点:实现简单,判定效率高

问题:很难解决对象之间相互循环引用的问题

可达性分析算法

通过“GC Roots”对象为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象没有任何引用链与其相连时,则该对象不可用,就会判定为可回收对象。

2、强、软、弱、虚四种引用

强引用

强引用是在程序代码中普遍存在的,类似于Object obj = new Object()这类引用,只要强引用还存在,垃圾回收期永远不会回收掉被引用的对象

软引用

软引用是用来描述一些还有用但是非必需的对象,对于软引用关联着的对象,在系统将要发生内存溢出之前,将会把这些对象列进回收范围之内进行二次回收,如果这次回收还是没有获得足够的内存,才会抛出内存溢出异常

弱引用

弱引用也是用来描述非必需对象的,但是它的强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次垃圾回收发生之前,当垃圾回收器工作时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象

虚引用

弱引用也是用来描述非必需对象的,但是它的强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次垃圾回收发生之前,当垃圾回收器工作时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象

3、垃圾回收算法

标记清除

标记清除算法分为“标记”和“清除”两个阶段,首先标记出所有需要回收的对象,在标记完成之后统一回收所有被标记的对象。

适用场景:

  • 对象存活比较多的时候(老年代)

缺点:

  • 产生大量不连续的空间碎片,

  • 提前触发GC,空间碎片太多会导致程序运行过程中需要分配大对象时候,无法找到足够的连续内存而提前触发GC

  • 需要扫描两次,标记存活对象和清除存活对象

复制算法

复制算法将可用内存按照容量划分为大小相等的两部分,每次使用一块。当这一块内存使用完了,就将还存活的对象复制到另一块上,然后把已使用过的内存空间一次性进行清理。

对象存活很多时候,复制算法就需要大量的复制操作,效率就会降低。还有就是不想浪费50%的空间,在应对对象100%存活的极端情况时就需要额外的空间来进行分配担保,因此,老年代中一般不采用复制算法

适用场景:

  • 存活对象少 比较高效
  • 适合年轻代

缺点:

  • 需要内存空间
  • 需要复制移动对象

标记整理

标记过程与“标记清除”算法一致,然后让所有存活的对象都向一端进行移动,最后直接清理掉除此存活对象区域之外的内存。

优点:

  • 不会产生碎片,方便对象分配
  • 不会产生内存减半

缺点:

  • 需要扫描两次
  • 效率低

4、分代回收

现在的垃圾回收器,都会在物理上或者逻辑上,把这两类对象进行区分。我们把死的快的对象所占的区域,叫作年轻代(Young generation)。把其他活的长的对象所占的区域,叫作老年代(Old generation)。在年轻代中选用复制算法,老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记清理”或者“标记整理”算法。

具体的分代回收和各类垃圾回收器在下一篇文章中再总结

这篇关于面试官!垃圾回收千万别问我的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!