JVM的垃圾收集算法

简介

由于垃圾收集算法的实现设计大量的程序细节,而且各个平台的虚拟机操作内存的方法又各不相同。

何时开始垃圾回收?
在使用标记清除算法时,未引用对象并不会被立即回收.取而代之的做法是,垃圾对象将一直累计到内存耗尽为止.当内存耗尽时,程序将会被挂起,垃圾回收开始执行。

有如下几种收集算法:
 标记-清除算法
 复制算法
 标记-整理算法
 分代收集算法

标记-清除算法

标记-清除算法是最基础的收集算法,如同其名字一样,分为标记阶段和清除阶段。

  • 标记
    在此阶段,垃圾回收器会从mutator(应用程序)根对象开始遍历。每一个可以从根对象访问到的对象都会被添加一个标识,于是这个对象就被标识为可到达对象。

  • 清除
    在此阶段,垃圾回收器,会对堆内存从头到尾进行线性遍历,如果发现有对象没有被标识为可到达对象,那么就将此对象占用的内存回收,并且将原来标记为可到达对象的标识清除,以便进行下一次垃圾回收操作。

特别说明:在垃圾回收阶段,应用程序的执行会暂停,等待回收执行完毕后,再恢复程序的执行。

缺点
1,效率问题,标记和清除的效率都不高
2,空间问题,标记清除后会产生大量不连续的内存碎片,空间碎片大多可能会导致以后再程序运行的过程中需要支配较大的对象时,无法找到足够的连续内存而不得不提前触发另一次的垃圾收集动作
标记-清除算法,回收前后,如下图:
这里写图片描述

复制算法

复制算法它将可用内存按容量分为了大小相等的两块,每次只使用其中的一块。当这一块用完了,就将还存活的对象复制到另一块上面去,然后把已使用过的内存空间一次清理掉。这样每次都是对一块区域进行回收,内存分配也不用考虑内存碎片的复杂情况,只要移动堆顶指针按顺序分配内存即可,实现简单,运行高效。

只是这种算法的代价是将内存缩小为原来一半了,代价有些太高了。
复制算法,回收前后,如下图:
这里写图片描述

但是商业虚拟机都采用这种收集算法收集新生代。据IBM研究表明,新生代的对象89%都是“朝生夕死”,所以不用1:1比例,应该是一个大块比小块。虚拟机中是一个较大Eden空间和两块较小的Survivor空间。HotSpot虚拟机Eden和Survivor默认的比例是8:1,这样就只有10%的空间被浪费。但是我们无法保证每次回收都只有不多于10%的对象存活,当Survivor空间不够用就要依赖其他内存(老年代)进行分配担保。

标记-整理算法

对于复制收集算法在对象存活较高的时候就要进行很多的复制操作,效率就会降低。就是不想浪费大量的空间,就需要有额外的空间进行分配担保,以应对被使用的内存中所有对象都100%存活的极端情况,所以老年代就不能采用这种算法。

标记整理算法的标记和标记清除的标记过程是一样的,只是后续不一样,而是让所有存活的对象都向一端移动,然后直接清理边界以外的内存。

标记-整理算法,回收前后,如下图:
这里写图片描述

分代收集算法

当前的商业虚拟机都是采用”分代收集“,这种算法并没有什么新的思想。是根据对象存活周期的不同,将内存划分为几块。一般是把Java堆分为新生代和老年代,就根据各个年代的特点采用最适合的收集算法。

在新生代,每次垃圾收集都发现大批对象死去,只有少量存活,就选择复制算法。
在老年代,对象存活率高,没有额外空间进行担保分配,就采用标记-清除算法或者标记-整理算法进行回收。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值