javascript 是否有可能在对象即将被垃圾收集之前得到通知?

eqfvzcg8  于 2022-12-25  发布在  Java
关注(0)|答案(2)|浏览(125)

问题

使用FinalizationRegistry,可以在对象被垃圾收集后得到通知,但是,是否可以在此之前得到通知,以便我仍然可以访问数据并对其进行操作?
∮我想要达到的目标∮
我想实现一个内部存储数据的CompressedMap<K, V>,或者在Map<K, Buffer>中压缩,或者在Map<K, WeakRef<V>>中膨胀,由用户定义deflateinflate函数。
作为一个经典的Map<K, V>,如果用户持有一个Map中的值的引用,并更新它,它也应该在Map中自动更新(因为它是同一个对象),这就是为什么我需要将值保存在Map<K, WeakRef<V>>中,只有当它们将要被垃圾收集时才压缩并移动到Map<K, Buffer>中。
我已经考虑过的

SO问题:Can I get a callback when my object is about to get collected by GC in Node?

接受的答案显示了如何使用FinalizationRegistry,它在对象被垃圾收集并且不再可用之后触发回调。

每次修改后将值移动到收缩标测图

这需要将对象的每个字段都 Package 在getter/setter中,这有很多含义:
1.在每次修改后更新收缩的标测图会增加计算量。
1.对新字段(未 Package 在getter/setter中)的修改将被忽略。

  1. Package 每个对象的每个字段可能会对大型Map产生很大的内存影响,这将使"压缩Map"的目的落空。
    1.它将修改用户的对象。
    1.它会询问对象的边界在哪里。也许我们应该 Package 所有的字段,甚至是深的字段,也许不应该。这取决于用户的用例。

编写Node.JS插件并使用Node-API

我没有深入研究,但这将是最后的解决方案,因为我的实现将只兼容Node.JS。即使我专注于Node.JS,浏览器支持将是很好的。而且我从来没有写过Node.JS插件,我甚至不确定它是否允许我实现PreFinalizationRegistry

参考文献

dbf7pr2w

dbf7pr2w1#

开发人员不应该依赖于基本程序逻辑的清除回调。清除回调可能有助于减少程序过程中的内存使用,但在其他方面可能没有什么用处。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry#notes_on_cleanup_callbacks
与其等到对象完成,我建议在一段时间内没有使用它时使用setTimeout()来缩小它。
为此,您需要返回一个行为类似于Map<K, WeakRef<V>>的对象,并 Package 它而不是实际的Map,这样,如果超时后使用它,您就可以开始抛出异常。

vwkv1x7d

vwkv1x7d2#

假设一个未被引用的对象{a: 1, b: {c: 2}}仍然有一个对它的b子对象的引用,如果该对象被压缩然后被垃圾收集,对b的引用的保持器可能会说ref_to_b.c = 3,并且这个变化不会自动反映在压缩版本中,所以当压缩版本稍后被重新膨胀时,它仍然有b.c = 2
这意味着你只能压缩那些本身不是对象的对象成员,也就是说,原始值成员。每当这样的值被改变时,这可以用setter来完成。收缩的值将被保存在强引用中,这样只要知道对象的键,就可以从它们重新创建对象,即使它的早期化身已经被垃圾收集。

class DeflatableObject {
  static deflated = {
    primitive: new Map(),
    subobject: new Map()
  }
  static recreate(key) {
    var obj = new DeflatableObject();
    obj.key = key;
    obj._primitive = inflate(DeflatableObject.deflated.primitive.get(key));
    var subobj = DeflatableObject.deflated.subobject.get(key);
    if (subobj)
      obj._subobject = subobj.object.deref() || DeflatableSubobject.recreate(subobj.key);
    return obj;
  }
  set primitive(value) {
    this._primitive = value;
    DeflatableObject.deflated.primitive.set(this.key, deflate(value));
  }
  get primitive() {
    return this._primitive;
  }
  set subobject(value) {
    this._subobject = value;
    DeflatableObject.deflated.subobject.set(this.key, {
      object: new WeakRef(value),
      key: value.key
    });
  }
  get subobject() {
    return this._subobject;
  }
}

相关问题