关于V8内存回收的问题
发布于 7 年前 作者 meiwhu 3090 次浏览 来自 问答

先看下面两段代码;代码一会导致内存泄漏不被回收;代码二不会泄露。

之前一直以为两段代码都不会泄漏,因为unused未被引用,someMethod也没引用orginalThing,代码一确实泄漏了;我查看了相关资料,认为someMethod和unused都定义在同一函数内,它们有共同的lexical environment,unused引用了originalThing,所以someMethod也引用了originalThing,导致代码一内存泄漏。

由于楼主没阅读V8源码看看详细,觉得仅凭猜测和看他人博客不放心,所以请懂得道友来说说lexical environment时什么?以及相关的细节,感谢感谢!

代码一:

let theThing = null
let replaceThing = function () {
  let originalThing = theThing
  let unused = function () {
    if (originalThing) { }
  }
  theThing = {
    longStr: new Array(100000000).join('*'),
    someMethod: function () { }
  };
};
setInterval(replaceThing, 1000)

代码二:

let theThing = null
let replaceThing = function () {
  let originalThing = theThing
  let unused = function () {
    if (originalThing) { }
  }
  theThing = {
    longStr: new Array(100000000).join('*')
  };
};
setInterval(replaceThing, 1000)
5 回复

我个人的理解(没阅读过v8源码,如果有什么不正确的地方请指正,谢谢),这其实跟闭包一个原理。把一个内部定义的函数someMethod赋值给了全局变量,在someMethod内由于作用域链关系,是内部是可以访问到这个闭包内的unused和originalThing,所以这两个变量没有被回收。计时器一直执行,就造成了内存泄露。

@foora 如果按你说的可以访问就不被回收,那么不写unused函数依然会泄漏内存了,但实际上不会泄露的。

一直理解来理解去也没什么意思,我想知道v8的实现方法。

回到顶部