【发布时间】:2016-01-05 19:10:03
【问题描述】:
查看 Chrome 堆快照的这一部分:
它显示了堆中一个对象的保持器,据我所知和可以看到,它应该是垃圾,但尽管如此,它并没有被收集。
到根的“最短”路径毕竟是一条循环路径(它实际上从未到达根)。这让人不禁想知道,快照查看器是如何为它分配 12 的距离的呢?这仅仅是放弃之前通过循环所采取的步骤数吗?请注意距离永远不会低于 11。
我了解到,清理带有循环引用的子图可能需要几次迭代。但重复的强制收集(使用“时间轴”选项卡中的垃圾桶按钮)未能清理这些对象。
请注意,通过“185”引用探索最终会导致相同的system / Context @862399,因此实际上没有从根到该对象的路径(至少在此处不可见)。
是我疯了,还是垃圾收集器真的坏了?我不记得过去有这个问题。我在 Chrome 45.0.2454.101 上。 Beta 46.0.2490.64 的行为相同。
【问题讨论】:
-
这些方法甚至可以被垃圾收集吗?你在创建闭包吗?您会无意中造成内存泄漏吗?
-
Google JavaScript style guide 有一个闭包示例,该闭包创建了导致内存泄漏的循环引用。如果这是 OP 的情况,那么这并不是什么新鲜事:1、2、3。不知道为什么,但现代 JS 引擎似乎没有解决这个非常常见的内存泄漏源的解决方案。
-
@GOTO0 我知道闭包会保留对它使用的封闭变量的引用(否则它怎么能起作用?)但它还保留未使用的封闭变量对我来说是新的,实际上很漂亮令人失望。但是,该样式指南说“循环引用,因此存在内存泄漏”。这不是仅适用于引用计数 GC 的过时声明吗?我认为标记和扫描应该使这成为一个非问题?如果那部分是错误的,那么该指南的其余部分是否值得信赖?
-
@GOTO0 我做了一个小测试:pastebin.com/fPxNxqSy。尽管
x返回的闭包被window保留,但在那里创建的MyClass实例m并没有保留(如堆快照所示)。保留y中的那个,因为eval无法优化掉它。 (这是 V8 中的一个实现细节,虽然我怀疑其他现代浏览器的行为相同,但我还没有测试过。) -
Google 风格的代码链接只是某人的建议,尽管是来自 google 的人,所以对于任何建议文章,您都应该这样对待。有一些众所周知的旧文章是基于证据的,有很棒的建议和例子。但是,您将找到的最佳文档将是您的 chrome 配置文件和内存使用情况。使用您的应用程序一段时间,然后将其保持打开状态,这将比一篇文章或我的/任何答案更能帮助您确定您的内存管理机会。
标签: javascript google-chrome garbage-collection v8 circular-reference