微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

JVM学习(四)垃圾清理

垃圾收集的核心目标(重点)

这三个问题肯定要会答

  • 哪些内存需要回收
  • 什么时候回收
  • 如何回收

哪些内存需要回收(重点)

  • 程序计数器,虚拟机栈,本地方法栈随线程而生,随线程而灭不需要过多考虑内存回收
  • Java堆和方法区作为共享区域具有显著的不确定性,其对象的分配和回收都是动态产生的。

什么时候回收(重点)

可达性分析算法 (这个必背,除了这里还有下一篇的详细分析要会)

如上图所示,object1~object4对GC Root都是可达的,说明不可被回收,object5和object6对GC Root节点不可达,说明其可以被回收。

术语:

  • GCroot:根对象,也叫做起始节点集
  • reference chain:引用链,从GCroot出发根据引用关系向下搜索搜索过程走过的路径

在Java中,可作为GC Root的对象包括以下几种:(重点,而且要能举例)

引用分类

  • 强引用:正常的引用赋值,"Object obj = new Object()",只要强引用在,垃圾收集器就永远不会回收掉被引用对象
  • 软引用:在系统发生溢出异常前,才会把这些对象列入回收范围之中进行二次回收
  • 弱引用:关联的对象只能生存到下一次垃圾收集发生为止,hashmap那里有相关知识点
  • 虚引用:不用管,没啥用

如何回收(重点)

三个分代假说(了解)

  • 弱分代假说:大多数对象都是朝生夕灭的
  • 强分代假说:熬越多次垃圾收集过程的对象越难以消亡
  • 跨代引用假说:跨代引用相对于同代引用来说仅是少数

记忆集(了解)

跨代引用的解决方

假如只局限于新生代的收集,那么我们将错误的回收E;若想正确回收,那就需要对老年区同样做一次GC搜索,明显效率低下。(效率低下是基于跨代引用假说)

解决方案就是在新生代上使用一个全局的数据结构,称为记忆集。如果发现老年代的内存区域存在新生代的引用,那么将会将对象加入记忆集。垃圾回收时,记忆集里面的对象会加入GCroot,就避免了老年代的全遍历回收。

它需要在对象改变引用关系的时候维护记录数据的正确性,增加一些运行时开销,但比起收集时扫描整个老年代还是划算。

参考来源

这三个必背

标记-清除算法:

  • 标记阶段:先通过根节点,标记所有从根节点开始的对象,未被标记的为垃圾对象
  • 清除阶段:清除所有未被标记的对象

缺点:

  • 执行效率低,标记需要遍历一次堆,清除也要遍历一次堆
  • 内存空间碎片化,标记清除后产生大量不连续的内存碎片

标记-复制算法:

  • 标记阶段:先通过根节点,标记所有从根节点开始的可达对象,未被标记的为垃圾对象
  • 复制阶段:将原有的内存空间分为两块,每次只使用一块,在垃圾回收时,将正在使用的内存中的存活对象复制到未被使用的内存块中,然后清除正在使用的内存块中的所有对象。

缺点:

  • 空间浪费一半

标记-整理算法:

  • 标记阶段:先通过根节点,标记所有从根节点开始的可达对象,未被标记的为垃圾对象
  • 整理阶段:将所有的存活对象压缩到内存的一个统一区域,之后清理边界外所有的空间

 

三种算法的比较:

总结

面试如果让你介绍垃圾回收算法就这么泛泛谈即可,具体深入见下篇文章

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐