【问题标题】:Clean up after an object gets garbage-collected在对象被垃圾收集后清理
【发布时间】:2020-05-08 01:45:45
【问题描述】:

我正在开发一个具有以下功能的库:

  • 一些相当复杂的循环引用。
  • 注册各种事件监听器。
  • 为全局缓存使用一些(单一样式的)对象

这些属性意味着我的应用程序中的一堆东西不太可能被自动垃圾收集。

如果对象的最后一个引用被垃圾回收,我还想自动取消注册事件处理程序,增加更大药水的机会 的图书馆可以得到垃圾收集。

在 PHP 中,可以为此目的使用 __destruct 方法。 Javascript中是否有类似的机制?

从广义上讲,这将是我的依赖图的一个虚构示例:

Parent
  - childA
  - childB

Parent 在这种情况下只有外部引用,所以如果不再使用这个对象,Javascript 可以 GC,但是当这种情况发生时,我希望 Parent 通知 childAchildB 他们可以 de-注册他们的事件处理程序并进行额外的清理。

当然,我可以在父级上添加 release()destroy() 方法,但我希望它能够在不需要最终用户明确向父级发出信号的情况下工作。

【问题讨论】:

  • 您正在寻找weak references 及其终结者。另见v8.dev/features/weak-references。但就目前而言,release() 似乎是您最好的选择。
  • @Bergi 想把它变成答案吗?它对我有用!
  • 啊,一开始我没注意到你是用nodejs工作的,当然更适合使用实验性功能。

标签: javascript node.js garbage-collection


【解决方案1】:

如果对象的最后一个引用被垃圾回收,我还想自动取消注册事件处理程序,增加更大的库药水被垃圾回收的机会。

您正在寻找weak references 及其终结者。事件处理程序不会保留对实例的直接引用,而只会保留一个弱引用。当实例被垃圾回收时,终结器可以取消注册事件处理程序。

另见https://v8.dev/features/weak-references。不过,我没有看到任何关于 node.js 的声明已经支持这一点。

【讨论】:

    【解决方案2】:

    根据this SO questionthis v8 blog,node.js 不做引用计数,而是一个完整的标记和清除样式的垃圾收集。

    这意味着垃圾收集器从执行帧和global 对象开始,遍历所有引用,将它们标记为可达。完成后,它将所有无法访问的内存区域标记为“可用空间”。即使您的库有大量的循环引用和事件监听器,如果整个引用块/事件发射器本身不可访问,所有这些都将被标记和扫除。

    您通常不必担心,因为 v8 的垃圾收集器相当强大,但仍然需要注意在需要时释放不再需要的引用(或确保引用的短生命周期或其他此类技术) .

    【讨论】:

    • 不幸的是,我的代码中的某些位不会用这种方法触发。具体示例,我有一些事件触发某些用户操作。从 GC 的角度来看,这些对象肯定仍然存在全局引用,因此它们实际上不会被 GC。
    猜你喜欢
    • 1970-01-01
    • 2011-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-09
    • 1970-01-01
    • 1970-01-01
    • 2012-03-08
    相关资源
    最近更新 更多