垃圾回收与算法

垃圾回收与算法

GC要做的三件事:

  1. 哪些内存需要回收?(what)
  2. 什么时候回收?(when)
  3. 怎么回收?(how)

1 如何确定垃圾

由于引用计数法的循环引用问题,Java 使用的是可达性分析的方法。

1.1 引用计数法(Reference-Counting)

每个对象有一个引用计数器,当对象被引用一次则计数器加1,当对象引用失效一次则计数器减1,对于计数器为0的对象意味着是垃圾对象,可以被GC回收。

1.2 可达性分析(GC Roots Tracing)

从 GC Roots 作为起点开始搜索,那么整个连通图中的对象便都是活对象。如果在 GC Roots 和一个对象之间没有可达路径,则称该对象是不可达的。
不可达对象不等价于可回收对象,不可达对象变为可回收对象至少要经过两次标记过程。两次标记后仍然是可回收对象,则将面临回收。

2 回收垃圾的算法

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

最基础的垃圾回收算法,分为两个阶段:

  1. 标记
    标记出所有需要回收的对象
  2. 清除
    回收被标记的对象所占用的空间

标记清除算法
缺点:内存碎片化严重,后续可能发生大对象找不到可利用空间的问题。

2.2 复制算法(Copying)

为了解决标记清除算法内存碎片化的缺陷而提出的算法。
按内存容量将内存划分为等大小的两块,每次只使用其中一块。
当这一块内存存满后将尚存活的对象复制到另一块上去,把已使用的内存清掉:
复制算法
优点:实现简单,内存效率高,不易产生碎片。
缺点:可用内存被压缩到了原来的一半。存活对象增多时,复制算法的效率会大大降低。

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

结合了以上两个算法而提出。

  1. 标记
    标记出需要清理的垃圾。
  2. 整理
    标记后不是清理对象,而是将存活对象移向内存的一端,然后清除端边界外的对象。

标记整理算法

2.4 分代收集算法

分代收集法是目前大部分 JVM 所采用的方法。
其核心思想是根据对象存活的不同生命周期将内存划分为不同的域,一般情况下将 GC 堆划分为老生代(Tenured/Old Generation)和新生代(Young Generation)。
老生代的特点是每次垃圾回收时只有少量对象需要被回收,新生代的特点是每次垃圾回收时都有大量垃圾需要被回收,因此可以根据不同区域选择不同的算法。

2.4.1 新生代与复制算法

目前大部分 JVM 的 GC 对于新生代都采取复制算法,因为新生代中每次垃圾回收都要回收大部分对象,即要复制的操作比较少。
但通常并不是按照 1:1 来划分新生代。一般将新生代划分为一块较大的 Eden 空间和两个较小的 Survivor 空间(From Space, To Space),每次使用Eden 空间和其中的一块 Survivor 空间,当进行回收时,将该两块空间中还存活的对象复制到另一块 Survivor 空间中。
详见JVM运行时内存
新生代与复制算法

2.4.2 老年代与标记整理算法

老年代因为每次只回收少量对象,因而采用标记整理算法。
详见JVM运行时内存

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值