JVM-垃圾回收机制算法简述

  • 为什么要有垃圾回收机制 
    在编程语言的发展中,内存的动态分配与动态回收是必不可少的。当你一直在索取内存空间,而不去释放它,总有一次申请分配时,会出现内存溢出、内存泄漏等问题。这也是为什么我们要去了解这个”自动化”的机制的原因。

    1. 标记-清除算法(Mark-Sweep):标记清除其实这很接近标记-清除算法的理念。首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。它就是最基础的垃圾回收算法。但是这么做存在两个问题: 

  • (1)效率问题:标记过程与清除过程采用轮询一样的机制的话,效率太低;

    (2)空间问题:需要回收的对象内存空间并不一定是连续的,如果每隔一个单位内存空间就有一个对象需要回收,那么会出现 太多的控件碎片。导致后面的操作在申请较大的内存空间时,会出现实际内存容量足够,但是没有连续的内存空间去分配给这个对象的情况。导致不得不去触发另一次的垃圾收集动作。


  • 2.标记-整理算法(Mark-Compact)

  • 之后学长再次提问:你觉得怎么去解决内存碎片这个问题比较好?“在清理完成之后,把还在的对象一起移动到它们是连续的”。(思维有限,答案只是自己想法) 
  • 标记整理
  • 其实,标记-整理算法已经把“清除”步骤变成了“整理”。在同样进行标记完成后,让所有存活的对象向内存的一端移动,然后直接清除掉存活对象区边界之外的内存。其实这个算法应用大部分在于分代收集中的老年代中,下面一步一步介绍分代收集。
  • 3. 复制算法(Copying)

    为了解决标记-清除算法的效率问题,人们在它的基础上提出了复制算法。其实我更想称呼他为“标记-复制(移动)-清除”算法。
  • 复制
  • 我们可以把内存空间分为大小相等的两份,每次只使用其中的一块。当发现正在使用的一块的内存空间用完了以后,把还存活的对象复制到另一块内存空间上,再去清除上一块内存空间中需要清除的对象。每次操作对半个区域,没有了大量的内存碎片,通过堆指针的移动,效率也得到了提高。 
    重要的来了:这种算法存在一个缺陷是把可用内存缩小为了原来的一半。当对象大部分在下一次GC时都会被回收的情况下,50%的比例太大了。所以大部分时候是按照一种实践后的分配方式:

    • 将(新生代)内存空间分为一块80%空间的 Eden 空间和两块10%的 Survivor 空间,在GC时,将Eden与一块Survivor中的存活对象复制到另一块Survivor空间中。

    但是实际上,我们无法保证那10%就足以存储还存活的对象,所以我们还要依赖其他的内存空间,就是“老年代”,顺理成章地,上面的空间变成了“新生代”。

    分代收集算法

    当前的JVM基本都是使用分代收集算法。针对不同的情况,在不同的“代”中执行不同的垃圾回收算法。一般把 JVM堆内存 分为新生代与老年代。新生代对象死亡率高,使用复制算法。老年代中的对象存活率高,没有额外空间对它们进行分配担保,就必须使用Mark-Sweep、Mark-Compact.

    对于不同的垃圾收集器,会在不同的代使用大致相同的垃圾回收算法,但是有的是双阶段多线程,有的只有一个阶段使用。稍后,我会分析最近比较热门的CMS收集器与G1收集器中更加智能的过程。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值