week05_day05_GC(垃圾回收)

我们现在学虚拟机都是以hotspot为例来讲的。

GC——Garbage Collection
在JVM中,GC的功能是由垃圾回收器来完成。

研究GC,就必须要回答下面3个问题:

  1. 如何确定“垃圾”
  2. 如何回收垃圾
  3. 何时触发GC

···············································································································································································································

一、如何确定垃圾对象?

  1. 确定哪些对象已经变成了垃圾,最简单的算法就是引用计数法
    给对象添加一个引用计数器
    每当一个地方引用它时,计数器加1
    每当引用失效时,计数器减少1
    当计数器的数值为0时,也就是对象无法被引用时,表明对象不可在使用
    week05_day05_GC(垃圾回收)

但是这个算法存在一个致命的缺陷,无法解决循环引用的问题

为此,引入了另外一种跟搜索算法

2. 根搜索算法
这个算法的基本思想是将一系列称为“GC Roots”的对象作为起始点
从这些节点开始向下搜索
搜索所走的路径称为引用链
当一个对象到所有的GC root之间没有任何引用链相连,时,就认为该对象变成了垃圾

GC Roots包含对象呢?
虚拟机栈中引用的对象
方法区中的静态属性引用的对象
(这两种都是可用对象)
week05_day05_GC(垃圾回收)
···············································································································································································································

二、如何回收垃圾对象呢?

  1. 标记清除算法(Mark Sweep)
    缺点:易产生内存碎片
    week05_day05_GC(垃圾回收)
    week05_day05_GC(垃圾回收)
  2. 标记复制算法(Copy)
    week05_day05_GC(垃圾回收)
    这个堆内存,上来不管三七二十一,先切一半,只用一半给对象分配存储空间,剩下一半不使用。
    然后这一半用啊用啊快用完的时候,如果还有人来new对象,此时就会触发一次垃圾回收,复制算法把存活对象复制到另一片存储空间中,然后将原来这半边的内存全部回收掉。
    然后就使用另一半存储空间给应用程序分配内存。
    然后就这样循环,这半边满了移到对面,回收这半边,对面那半边满了移到这半边,回手对面那半边。
    week05_day05_GC(垃圾回收)
  3. 标记整理算法(Mark Compact)
    week05_day05_GC(垃圾回收)

这个算法做了两件事情:
a. 回收垃圾对象
b. 将所有存活对象向内存的同一端移动。将每一个存活对象移动到上一个存活对象之后。

所以,其内存利用率很高(不用上来就砍一半),也不会产生内存碎片。
但是,因为移动存活对象会计算上一个存活对象的地址,所以会花费很多时间,效率比较低。(用时间换空间)