为什么 JVM 不能确保所有垃圾都会被回收?

垃圾回收

垃圾回收包含两个步骤,1、标记哪些内存是垃圾;2、内存回收

一、标记算法

1、引用计数算法 - 经典算法,但没有 JVM 采用

​ 堆中的每个对象都有一个引用计数器,根据引用计数是否等于零来判断是否需要被回收;

优点:判断是否需要回收的效率高,不需要额外的线程做 GC 的工作;

缺点:无法识别循环引用的情况,增加额外开销;

2、根搜索标记算法

步骤:

第一步:获取不可达对象

​ ① 暂停整个应用;

​ ② 生成 根集 GC root;

​ ③ 从根集出发,找出根集中的对象引用的其他对象,生成应用链;

​ ④ 根据引用链获取所有不可达的对象;

第二步:判断对象是否重载了 finalize 方法,如果没有,直接标记为可回收对象。否则加入 F-Queue 中,等待执行 finalize 方法。

if obj override finalize:
    F_queue.add(obj)
else:
    unreachable_list.add(obj)

第三步:如果 F-Queue 中的对象执行完 finalize 方法后,对象仍然不可达,标记为可回收对象。如果在 finalize 方法中,其他对象又持有了该对象,将不会被标记。

for obj in F_queue:
    obj.finalize()
    if is_reachable(obj):
        reachable_list.add(obj)
    else:
        unreachable_list.add(obj) 
二、垃圾收集

垃圾收集算法主要有三种:

  • 标记清除算法
  • 标记压缩算法
  • 复制算法
标记清除算法

工作方式:1、JVM 内部维护一张表,用于记录空闲内存的地址和大小;2、工作时,先将标记为可释放的对象的内存释放,然后更新表中的数据;

优点:速度快,不需要移动内存

缺点:会产生大量的内存碎片,维护一张表有额外的开销,分配新内存时,需要遍历空闲列表找到合适的内存块

标记整理算法

工作方式:1、移动活跃的对象,依次移动到内存的一端;2、移动完毕后,清理边界之外的内存

优点:不会产生内存碎片

缺点:由于需要移动内存,暂停应用的时间会延长;

特点:算法的耗时,跟堆大小有关,因为需要遍历一次堆大小,以确保把所有活跃对象都移动到了内存的一端;

复制算法

工作方式:1、将堆内存分为两块相同的区域,其中一块负责分配内存,当不够分配时,将活跃对象依次复制到另一块区域,然后一次性清理掉旧的内存区域,接着用于分配内存

优点:1、不会产生内存碎片;2、标记和复制可以同时进行;3、清理效率高

缺点:1、可分配的对内存减少了一半;2、由于需要移动内存,暂停应用的时间会延长;

特点:该算法的耗时,只跟活跃对象的数量有关,跟堆空间总大小无关;

三、分代回收

现代垃圾回收器,都是分代垃圾回收器,他们建立在两个分代理论之上

  • 大多数对象在年轻的时候死亡
  • 越老的对象越难死亡

基于分代理论,可以更高频率地回收 年轻代,更低频率地回收 老年代,从而兼顾垃圾回收的 时间开销 和 内存的空间利用率。但是有一个缺陷,有些 年轻代 对象可能被 老年代 对象应用,如果不遍历 老年代,将无法找出被 引用的年轻代。反过来也是如此。为了解决这个问题,垃圾回收器额外使用了一个表,用来记录每个 跨代引用。这样就不需要遍历整个老年代了。所以说跨代引用也是 GC root。但是这又将引入另一个问题,就是某些老年代可能已经不可达了,但是因为还没被 GC,所以它一直存活着,所以它所引用的 年轻代 也不能得到释放。所以说 垃圾回收确保回收的对象必然是不可达对象,但是不确保所有的不可达对象都会被回收

年轻代 和 老年代 的回收算法

对于 年轻代 的对象,他们数量多,生命周期短,而且大部分都是要回收的,复制算法,特别适合年轻代的回收;对于 老年代 对象,他们占用内存大,不能使用复制算法,而且需要避免内存碎片,所以使用标记整理算法。

特点回收算法
年轻代数量多、生命周期短复制算法
老年代占用内存大标记整理算法
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值