V8的垃圾回收策略主要是基于分带式垃圾回收机制
,根据对象的存活时间将内存的垃圾回收进行不同的分代,然后对不同的分代采用不同的垃圾回收算法
新生代回收机制
新生代的垃圾回收过程主要是用Scavenge算法,在Scavenge算法的具体实现中,主要采用了Cheney算法,将新生代内存一分为二,每个部分的空间称为Semispace,其中处于激活状态的区域称为From空间,未激活的区域称为To空间。这两个空间中,始终只有一个处于使用状态,另一个处于闲置状态。程序中声明的对象首先会被分配到From空间,当进行垃圾回收时,回收From空间中没有引用的对象,将剩余的对象复制到To对象中,当复制完整之后From空间和To空间完成角色互换
对象晋升到老生代
当一个对象经过多次复制之后依旧存活,那么它会被认为是一个生命周期较长的对象,在下一次进行垃圾回收时,该对象会被直接转移到老生代中,这种对象从新生代转移到老生代的过程称为晋升
对象晋升的两个主要条件(满足一个就行):
- 对象是否经历过一次Scavenge算法
- To空间的内存占比是否已经超过25%
老生代使用标记清除法
和标记管理法
进行管理
标记清除分为标记和清除两个阶段,在标记阶段会遍历堆中的所有对象,然后标记活着的对象,在清除阶段中,会将死亡的对象进行清除。标记清除算法主要通过判断某个对象是否可以被访问到,从而知道该对象是否应该被回收,具体步骤如下:
- 垃圾回收器会在内部构建一个根列表,用于从根节点出发去寻找那些可以被访问到的变量。
- 垃圾回收器从所有根节点出发,遍历其可以访问到的子节点,并将其标记为活动的,根节点不能到达的地方即为非活动的,将会视为垃圾
- 垃圾回收期释放所有非活动的内存块,将其归还给操作系统
可以作为根节点
- 全局对象
- 本地函数的局部变量和参数
- 当前嵌套调用链上的其他函数的变量和参数
标记管理法是为了解决内存碎片的问题,是在标记完成后,在整理的过程中,会将活动的对象往堆内存的一端进行移动,移动完成后再清理掉边界外的全部内存