Duktape中对象被删除或释放时如何执行对应的清理任务?
问题解答
首先直接给出结论:
- 标准JavaScript没有提供原生的析构函数自动触发机制,你自定义的
destructor原型方法不会在GC回收MyClass实例时被自动调用,完全无法实现你要的自动释放native buffer的需求。 - 你自行分配的native内存不属于JavaScript GC的管理范围,如果没有主动触发释放逻辑,会持续造成内存泄漏。
正确的实现方案
你可以根据你的运行环境和业务场景选择以下方案:
方案1:手动生命周期管理
最通用、兼容性最好的方案,你可以保留现有的释放逻辑,但是要求所有使用MyClass的开发者在实例使用完毕后,主动调用释放方法:// 定义释放方法 MyClass.prototype.free = function () { if (this.buffer) { native.free(this.buffer) this.buffer = null } } // 使用示例 const instance = new MyClass() // 执行业务逻辑... // 用完主动释放 instance.free()方案2:GC回收自动回调(ES2021+支持)
如果你运行环境支持ES2021,可以使用FinalizationRegistry注册对象回收回调,在实例被GC回收时自动释放buffer:// 全局注册Finalization回调 const bufferReleaseRegistry = new FinalizationRegistry((buffer) => { native.free(buffer) }) MyClass = function () { this.buffer = native.alloc() // 注册当前实例,实例被回收时会把第二个参数传入回调 bufferReleaseRegistry.register(this, this.buffer) }注意该方案存在局限性:GC的运行时机是完全由引擎控制的,无法保证buffer会被及时释放,极端场景下可能出现内存占用过高的问题,不适合对资源释放及时性要求高的场景。
方案3:块级自动释放(ES2022+支持)
如果你的运行环境支持ES2022的显式资源管理,可以实现Symbol.dispose接口,配合using声明实现离开作用域自动释放:MyClass.prototype[Symbol.dispose] = function () { native.free(this.buffer) } // 使用示例 { using instance = new MyClass() // 块内执行业务逻辑 } // 离开块作用域时,会自动调用instance[Symbol.dispose]完成释放
内容的提问来源于stack exchange,提问作者Link Hylia
相关产品推荐
相关产品推荐

