QuickJS 是使用引用计数法来判断对象是否可以被释放,引用计数法非常简单,通过给对象分配一个计时器来保存该对象被引用的次数,如果该对象被其它对象引用就会加1,如果删除引用就会减1,当引用的计数器为0时,那么就会被回收。
JSRuntime 是 QuickJS 最底层的执行环境,不使用的时需要及时释放。
一个 JSRuntime 可以创建多个 Context,每个 Context 之间是相互隔离的,不使用的时需要及时释放。
如果我们需要自己创建和关联JS对象时,我们需要处理好引用问题,必须通过 c 创建一个JSValue对象,那么我们就需要手动释放它,否则就会导致内存泄漏,同时我们也不能多次释放,这也会导致野指针,从而导致程序崩溃,如果我们只是纯粹运行js脚本就无需我们关心这个问题,引擎已经处理好了。
通过上面示例,我们得知引用计数法是通过JS_DupValue记录引用+1,JS_FreeValue引用减1实现计数,接下来就通过源码分析如何实现。
引用计数器头是一个结构体,目前只有一个int值,用于记录对象的引用次数。
引用计数器+1
JS_FreeValue 处理引用计数器-1,如果引用属于小于0时候就会执行垃圾回收,这里引入引用计数器最大的问题,如果a引用b,b也引用了a,这样的相互应用是不是就会导致a和b都无法回收?
JS_RunGC 函数就是用来解决相互引用问题,会在特定的时机触发。
经过上面两个函数,tmp_obj_list 就只会剩下环形引用的对象,gc_free_cycles() 回收 tmp_obj_list 列表的对象,并且对属性的引用-1。
1、原理js按照固定的时间间隔找到不在继续使用的变量,释放其占用的内存。
2.实现方式
(1)标记清除
垃圾收集器给存储在内存上的所有变量都加上标记;
之后,去掉环境中的变量以及被环境引用变量的标记;
之后,被加上标记的变量就是准备删除的变量(原因是环境中的变量无法访问到这些变量了)。
目前,IE、firefox、opera、chrome和Safari浏览器都是标记清除的垃圾回收策略,只是回收时间间隔不一样。
(2)引用计数
原理:记录每个变量被引用的次数。释放引用计数为0的变量所占用的内存。
IE9 将BOM和DOM对象转换成了真正的js对象。
3、管理内存
背景:分配给浏览器的可用内存通常会比桌面应用程序少。
因此,如何使用最少的内存让页面获得最优的性能,就需要考虑管理内存。
一个比较好的做法是:解除引用,即不再使用的变量设置为null。