为什么我的Chrome Profiler没有为我的对象显示正确的保留路径,为什么我的对象永远不会被释放?

Oha*_*ick 23 javascript debugging profiler memory-leaks google-chrome

我正在尝试调试我的webapp中的内存泄漏.

我拍摄堆的快照并比较不同的堆.

我发现我的一些物体正在某处被引用.但是,我的所有对象都通过看起来像我内部的对象来保留,例如:

Profiler显示我的类被引用

正如您所看到的,这个SectionNavView对象是由我创建的一些方法引用的:cleanUp,hide,isShown等,使用我的局部变量,但这些方法是从我无法控制的东西中引用的:idToWrappedObject.有时,还有另一个中介 - 一个injectScript对象.

如果我的对象仅被内部V8引用引用,那么它们是否应该在分析器在GC期间拍摄快照之前被释放?

gui*_*ume 36

这只是意味着你已经习惯了console.log.因此,VM会保留对对象的引用,以便您以后检查它们.您可以停止使用控制台,也可以在每次执行堆快照时清除它.

您可以使用以下步骤重现它:

  1. 打开新标签
  2. 打开控制台(清除它,如果有的话)
  3. 获取堆快照1
  4. 键入console.log({ foo:'bar' })控制台
  5. 获取堆快照2
  6. 清除控制台
  7. 获取堆快照3

然后查看结果:

  1. 打开快照2和快照1之间的比较视图; 你会找到这个{ foo: 'bar' }对象

    比较快照1和2,foobar对象是可见的;  展开Object构造函数

  2. 打开快照3和快照2之间的比较视图; 你会发现同一个对象现在显示的增量为-1,这意味着在清除控制台后它会被垃圾收集

    比较快照2和3,foobar对象是可见的,但列delta显示它已被删除

最后,您还可以在保留树路径中看到"全局句柄",然后是"GC根",旁边_idToWrappedObjectInjectedScript.我不确定这如何适用于GC根的定义,但清除控制台确实允许垃圾收集.

  • 我甚至没有考虑console.log可能对堆快照有任何影响的可能性.+1就是为了那个.将重新测试并让你发布.真棒. (3认同)