- 手动回收 C++ 代码控制回收策略 不销毁回收则会导致内存泄漏
- 自动回收 JS JAVA 用垃圾回收器释放内存(GC Collector)
- 流程: 首先或创建其自身的执行上下文,然后将执行上下文压入调用栈中,执行完之后需要销毁其执行上下文,需要依靠一个
记录当前执行状态的指针(ESP)
,个人理解为标记指针,执行完这个执行上下文之后,这个ESP指针会向下移动到下一个要执行的执行上下文,这个下移的操作就是销毁执行上下文的过程。
-
使用JS的垃圾回收器
- 代际假说(The Generational Hypothesis)和分代收集
- 代际假说: 第一个大部分对象在内存存活时间短, 很多对象一经分配内存很快就不可访问,第二个是不死的对象,可以存活很久
- 代际假说(The Generational Hypothesis)和分代收集
-
V8把堆分为新生代和老生代两个区域,新生代存放的是生存时间短的对象(1-8M),老生代是生存时间长的对象
-
副垃圾回收器(新生代垃圾回收) 主垃圾回收器(老生代垃圾回收)
- 1.标记空间中活动对象和非活动对象
- 2.回收非活动对象所占据的内存, 标记玩之后统一清理内存中所有被标记可回收的对象
-
- 做内存整理,内存中大量不连续空间(内存碎片)可选项
-
新生区的垃圾回收 小对象(Scavenge算法)将新生代空间对半划分为两个区域, 一半是对象区域,一半是空闲区域, 新加入的对象都会存放到对象区域 ,当对象区域快写满时, 需要执行一个垃圾清理操作,清理完成之后,对象区域会与空闲区域进行翻转,翻转的操作还可以让新生代中的这两块区域无限循环重复使用下去。
-
新生区空间不大,很容易被存活对象装满整个区域,JS引擎采用对象晋升策略,经两次GC还存活的对象会移动到老生区中。
- 新生区晋升的对象会存放外,一些比较大的对象会直接存放到老生区。
- 特点: 对象占用空间大, 对象存活时间长
- 采用标记-清除算法(Mark-Sweep)进行垃圾回收
- 过程: 从一组根元素开始,递归遍历根元素,能到达的元素为活动对象,没到达的判断为垃圾数据,然后会进行清理垃圾数据,活动数据进行保留, 由于标记-清除算法是就地删除,会产生大量不连续碎片,所以有产生了另外一种(Mark-Compact)标记-整理算法, 在后面清除掉垃圾数据后,可活动数据会向一段移动,然后清除掉边界以外的内存
-
JS执行在主线程, 在执行垃圾回收时,在执行的JS脚本要暂停下来,等回收完毕后再恢复脚本执行
-
为降低老生代的垃圾回收造成的卡顿,出现一种新的算法,V8将标记过程分块分段,分成子标记过程,同时垃圾回收标记和JS脚本执行逻辑交替执行,知道标记阶段完成(增量标记算法(incremental Marking))