javascript - Chrome/V8 不垃圾回收循环引用?

标签 javascript google-chrome garbage-collection v8 circular-reference

看看 Chrome 堆快照的这一部分:

Chrome circular reference

它显示了堆中某个对象的保留器,据我所知,它应该是垃圾,但尽管如此仍未被收集。

毕竟,到根的“最短”路径是一条循环路径(它永远不会真正到达根)。这让人不禁要问,快照查看器是如何将 12 的距离分配给它的?这只是它在放弃之前通过循环所采取的步骤数吗?请注意距离永远不会低于 11。

我读到可能需要几次迭代才能清理带有循环引用的子图。但反复强制收集(使用时间轴选项卡中的垃圾桶按钮)未能清理这些对象。

请注意,探索“185”引用最终会导致相同的 system/Context @862399,因此实际上没有从根到此对象的路径(至少在这里不可见) ).

我是疯了,还是垃圾收集器真的坏了?我不记得过去有过这个问题。我使用的是 Chrome 45.0.2454.101。 Beta 46.0.2490.64 的行为相同。

最佳答案

老实说,我们需要快速查看您复制此代码的一些测试代码,但我对您遇到的情况有一个大概的了解。如果我错了,你可以提供一些测试代码来证明这一点,请告诉我。

您似乎已经知道,为了“清理”,Javascript 不希望再引用要释放的项目。

一个简单的例子:

// Currently not eligible for garbage
var myObj = {
    data : 'test'
};

// Reference data inside myObj
// A unique identifier to myObj.data now exists 
var myData = myObj.data;

// Whoops
myObj = 'something else';

// Because myData exists, so does data and can not be freed either, understandable
// This sounds simple and logical but most do not understand what is happening in the engine
// A relationship has been born between 'myData' and 'data' and as long as it exists, it is not eligible for garbage and remains in memory
console.log( myData );

您的代码可能比这更复杂,但这可能有助于解释在某个地方如何无法收集垃圾,因为可以遵循作用域链到引用。

考虑以下问题

function oops(text){

    function doStuff(){
        return text.toLowerCase();
    }
    return doStuff();
}

// 'doStuff' stays alive thanks to 'test' below.
var test = oops('closure');

doStuff 函数不会被垃圾回收,因为它正被 test 引用。

// You can see where this is headed. We have 2 references to the same 'doStuff' function object with separate unique identifiers now below.
var test2 = oops('closures...');

// This is now another unique identifier to 'doStuff'
var test3 = test2;

// doStuff survives yet still
test = 0;
test2 = 0;

// Now we let the function object of 'doStuff' be freed because there is no longer any references to it
test3 = 0;

这本质上是我们造成的内存泄漏。每次调用 oops 时,您都在创建一个具有唯一标识符的函数对象 doStuff

避免这种情况的方法可能是

function doStuff( text ){
    return text.toLowerCase();
}

function oops( text ){
    return doStuff();
}

var test = oops( 'closure' );

现在我们没有内存泄漏了。 doStuff 正在调用 而不是创建

仔细查看您的代码,您会发现您可能在某处执行此操作。

如果你正在搞乱元素,我想你可能会,IBM has a good article about circular references你可能想看看。


已经晚了,其中一些未经测试,但理论仍然存在,所以如果我拼写错误等,请告诉我,明天我可以查看此页面的 future 访问者。

关于javascript - Chrome/V8 不垃圾回收循环引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33011097/

相关文章:

javascript - bl.ock 预览中未在 localhost 中出现错误

javascript - 点击注册 1d 战舰游戏。使用数组记录以前的用户输入,然后与当前输入进行交叉检查

javascript - JavaScript 中的 "name"变量有什么特别之处?

c# - 程序员真的应该关心在 .NET 中创建对象的数量和/或频率吗?

javascript - 如何根据浏览器检测更改图片

.net - 有没有办法跟踪 javascript 的命中率?

google-chrome - fancybox youtube 覆盖

css - 带有剪辑路径的 SVG 直线路径在 Chrome 中不可见

c - 在从 C 回调期间保护小堆上的指针

memory-leaks - GenServer 进程的内存泄漏