垃圾回收的经典算法

 1. 引用计数方法
      引用计数(Reference Counting)算法是每个对象计算指向它的指针的数量,当有一个指针指向自己时计数值加1;当删除一个指向自己的指针时,计数值减1,如果计数值减为 0,说明已经不存在指向该对象的指针了,所以它可以被安全的销毁了。
      优点:内存管理的开销比较均匀,这样进行没有长时间的挂起内存管理的时间比较稳定,可以获得比较平滑的响应时间。
      缺点:首先能看到的一点是时间上的开销,每次在对象创建或者释放时,都要计算引用计数值,这会引起一些额外的开销;第二是空间上的开销,由于每个对象要保持自己被引用的数量,必须付出额外的空间来存放引用计数值。不过该算法还有先天性的缺陷,也就是该算法不能解决”循环引用“的问题。所谓循环引用就是两个对象之间互相引用,那么这两个对象的引用计数就不可能为0,也就不能被回收。这跟进程/线程之间的死锁有点类似。

  2.标记清除 
      标记-清除(Mark-Sweep)算法依赖于对所有存活对象进行一次全局遍历来确定哪些对象可以回收,遍历的过程从根出发,找到所有可达对象,除此之外,其它不可达的对象就是垃圾对象,可被回收。整个过程分为两个阶段:标记阶段找到所有存活对象;清除阶段清除所有垃圾对象。
内存单元不会被立即回收,而是处于不可到达状态,直到所有的内存都被耗尽,进行全局级别的遍历来确定哪些单元可以回收.显然这种全局级别的中断在实时性要求较高的系统并不实用,甚至视频游戏都不可能接受在GC时有这么长的停顿.如果实时性方面要求不高,标记清除可以获得比引用计数更好的性能.标记清除的代价还是较高,标记是全局级别的,算法复杂度与整个堆大小成正比.

 3.节点复制
       节点拷贝算法由于在拷贝过程中,就可以进行内存整理,所以不会再有内存碎片的问题,同时也不需要再专门做一次内存压缩。,而它最大的缺点在于需要双倍的空间。
将堆分成两个半区,一个包含现有数据,另一个包含已经被废弃的数据,运行时两个半区的角色不断交换;这样做的优势在于内存分配的开销很小,只需要比较指针,不存在内存碎片的问题.但是内存浪费较大。

 4.标记-整理缩并
      是为了解决内存碎片问题而产生的一种算法,标记所有的存活对象 通过重新调整存活对象位置来缩并对象图;更新指向被移动了位置的对象的指针。

 5. 分代回收 
     是基于统计学原理的:多数内存块的生存周期都比较短,垃圾收集器应当把更多的精力放在检查和清理新分配的内存块上
它的基本思路是这样的:程序中存在大量的临时对象,分配出来之后很快就会被释放,而同时如果一个对象分配出来之后相当长的一段时间内都没回收,那么极有可能它的生命周期很长,尝试收集它会是无用功。所以可以把内存有意识地按“对象年龄”分成若干块,不妨记为老中青(XD),所有的分配都在青代进行,青代塞满只对青代做 GC,然后把存活下来的对象移动到中代,直到中青代都塞满,再把存活下来下来的对象移动到老代 —— 这只是个思路上的例子,实践中分代式垃圾收集算法的方案五花八门,而且常常同时使用了不止一种基本算法(比如青代用节点复制,老代用标记清扫啥的)。
     减少对常驻内存的对象GC次数.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值