一、回收策略
v8垃圾回收策略主要采用分代式回收机制,根具对象存活时间进行分代,将内存分为新生代和老生代两块内存空间。
然后将对象存活时间较短的分配到新生代内存中,新建的对象也是优先分配到新生代内存中,将对象存活时间较长的分配到老生代内存中,然后两个不同的生代采用不同的算法进行垃圾回收。
二、回收算法
1、Scavenge算法(用于新生代垃圾回收机制)
在分代的基础上,新生代中的对象主要通过Scavenge算法进行垃圾回收。而在Scavenge的具体实现中,主要采用了Cheney算法。
Cheney算法是一种采用复制的方式实现垃圾回收的算法。
它将新生代堆内存一分为二,每一部分空间称为semispace。
在这两个semispace空间中,只有一个处于使用中,另一个处于闲置状态。
处于使用状态的semispace空间称为From空间,处于闲置状态的空间称为To空间。
当我们分配对象时,先在From空间进行分配。当开始进行垃圾回收时,会检查From空间中的存活对象,这些存活对象将被复制到To空间中,而非存活对象占用的空间将会被释放。
完成复制后,From空间和To空间的角色发生对换,称为翻转。
优点:
Scavenge由于只复制存活的对象,并且对于生命周期短的场景存活对象只占少部分,所以它在时间效率上有优异的表现。
缺点:由于只能使用堆内存的一半,所以不适用大规模的垃圾回收机制中,是典型的牺牲空间换时间的算法。
2、Mark-sweep 和 Mark-compact 算法(用于老生代垃圾回收机制)
当一个对象经过多次复制依然存活时,它将会被认为是生命周期较长的对象。
这种较长生命周期的对象随后会被移动到老生代中,采用新的算法进行管理。
对象从新生代中移动到老生代中的过程称为晋升。
晋升条件:
对象晋升的条件主要有两个。
1、对象在新生代期间是否经历过Scavenge回收;
2、是To空间的内存占用比超过限制(To空间内存消耗是否超过25%,如果超过对象直接晋升)。
Mark-sweep 称为对象标记和清除,顾名思义该算法执行了两个步骤,标记和清除。
标记:
标记存活的对象
清除:
清除未被标记的对象,也就是死亡的对象
Mark-Sweep最大的问题是在进行一次标记清除回收后,内存空间会出现不连续的状态。
这种内存碎片会对后续的内存分配造成问题,因为很可能出现需要分配一个大对象的情况,这时所有的碎片空间都无法完成此次分配,就会提前触发垃圾回收,而这次回收是不必要的。
然而为了解决Mark-Sweep的内存碎片问题,Mark-Compact被提出来。
Mark-Compact是标记整理的意思,是在Mark-Sweep的基础上演变而来的。
它们的差别在于对象在标记为死亡后,在整理的过程中,将活着的对象往一端移动,移动完成后,直接清理掉边界外的内存。
Mark-Sweep与Mark-Compact两者为策略递进关系,当空间不足以对从新生代中晋升过来的对象进行分配时才使用Mark-Compact,在整理的过程中,将活着的对象往一端移动,移动完成后,直接清理掉边界外的内存。
完成移动后,就可以直接清除最右边的存活对象后面的内存区域完成回收。