JVM虚拟机夯实系列-垃圾收集算法

垃圾收集算法

分代收集理论:

当前虚拟机的垃圾收集器大都采用分代收集的思想。分代收集将Java堆内存划分为新生代(Young Generation)老年代(Old Generation)。在新生代中每次垃圾回收都会发现有大量对象死去,每次回收存活下来的一些对象则进入老年代中存放。

分代收集基于以下三个假说:

①弱分代假说:绝大多数对象都是朝生熄灭的。

②强分代假说:熬过越多次垃圾回收的对象就更难以消亡

③跨代引用假说:跨代引用相对于同代引用来说仅占极少数

基于以上假说我们可以得到结论是,存在相互引用关系的对象,是应该倾向于同时生存或者同时灭亡的。

针对跨代引用,为了节省时间不去扫描整个老年代,同时也不必浪费空间区专门记录每一个对象是否存在或者存在哪些跨代引用,只需要在新生代中建立一个全局的数据结构称为记忆集。这个结构会将老年代划分为若干小块,标识出老年代的哪一块内存存在跨代引用。

此后当发⽣Minor GC时,只有包含了跨代引⽤的⼩块内存⾥的对象才会被加⼊到GC Roots进⾏扫描。虽然这种⽅法需要在对象改变引⽤关系(如将⾃⼰或者某个属性赋值)时维护记录数据的正确性,会增加⼀些运⾏时的开销,但⽐起收集时扫描整个⽼年代来说仍然是划算的。

***垃圾收集名词:

部分收集(Partial GC):目标不是完整收集整个Java堆里的垃圾收集。

     *新生代收集(Minor GC/Young GC):目标只是新生代的垃圾收集。

     *老年代收集(Major GC/Old GC):目标指示老年代的垃圾收集。CMS收集器值进行单独老年代收集的行为。

     *混合收集:目标是整个新生代和部分老年代的垃圾收集。只有G1收集器会有这种行为。

整堆收集:收集整个Java堆和方法区的垃圾收集。

标记-清除算法:

分为两个阶段,先“标记”再“清除”首先对需要回收的对象进行标记(标记原理在引用一节中的PS两次标记过程),其次再标记完成后统一回收

主要不足是效率不高会产生不连续的空间碎片

复制算法(新生代多采用):

该算法相比标记删除算法解决了效率问题。原理是将可用的内存分为两块,每次使用其中的一块,另一块内存空闲,当第一块内存用完后,将其还存活的对象复制到空闲内存中,并把原来的内存全部进行回收

不用考虑会产生空间碎片的情况,只要移动堆顶指针按顺序分配内存即可。

因为新生代的存活率比较低,所以虚拟机都采用这种算法进行新生代回收。这种分代布局具体实现算法时,是将内存划分为一块Eden空间两块较小的Survivor空间,每次使用一块Eden空间和一块较小的Survivor空间,回收时将这两块空间中还存活的对象复制到另一块Survivor空间中,最后清理掉使用的两块空间。

且实现算法时不需要按照1:1的比例来划分内存,一般是划分为8:1的Eden空间和Survivor空间。也就是说新生代90%的的空间都可用,只浪费10%。但当存活的对象超过10%的时候,也就是说Survivor空间不够用了,这时需要老年代进行分配担保多出的对象直接进入老年代。

实现简单高效,但是浪费内存

标记-整理算法(老年代多采用): 

这种算法多针对存货对象较高的情况,也分为两步骤“标记”和“整理”,首先是对需要回收的对象进行标记,其次是将所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。

然而,每次移动大量存活对象并更新对于虚拟机是一种极为负重的工作,这种移动对象的操作可以需要暂停用户程序才能继续进行,这种工作造成的停顿也被称为“Stop The World”(STW)

但如果跟标记-清除算法那样完全不考虑移动和整理存活对象的话,弥散于堆中的存活对象导致的空间碎⽚化问题就只能依赖更为复杂的内存分配器和内存访问器来解决。譬如通过“分区空闲分配链表”来解决内存分配问题(计算机硬盘存储⼤⽂件就不要求物理连续的磁盘空间,能够在碎⽚化的硬盘上存储和访问就是通过硬盘分区表实现的)。内存的访问是⽤户程序最频繁的操作,甚⾄都没有之⼀,假如在这个环节上增加了额外的负担,势必会直接影响应⽤程序的吞吐量

基于以上两点,是否移动对象都存在弊端,移动则内存回收时会更复杂,不移动则内存分配时会更复杂。从垃圾收集的停顿时间来看,不移动对象停顿时间会更短,甚⾄可以不需要停顿,但是从整个程序的吞吐量来看,移动对象会更划算。 

吞吐量=运行用户代码时间/(运行用户代码时间+运行垃圾收集时间)

HotSpot虚拟机⾥⾯关注吞吐量的Parallel Scavenge收集器是基于标记-整理算法的,⽽关注延迟的CMS收集器则是基于标记-清除算法的,这也从侧⾯印证这点。CMS收集器在面临空间碎片过多时会采用“和稀泥”的方法,在空间碎片处于可容忍范围内时,采用标记清除算法,当空间碎片达到一定数量时采用标记整理算法。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值