目录

napi关联的c层对象无法触发GC

问题现象

在ArkTS创建一个对象,通过napi_wrap将ArkTS对象与Native的C++对象绑定,第一次创建ArkTS对象后触发napi_wrap的垃圾回收回调,等回收完成后再次创建对象,垃圾回收回调不会触发。

ArkTS侧创建对象:

C++侧构造函数和析构函数:

napi_wrap绑定ArkTS对象与C++对象:

背景知识

问题定位

多次创建对象,析构执行后,再次创建对象不会再执行析构。

分析结论

ArkTS侧的变量大小如果没有达到GC触发水位线,此时C++侧内存大小不在触发水位线计算范围内,不会触发GC行为,napi_wrap绑定的析构处理回调也不会调用。

修改建议

将napi_wrap替换为napi_wrap_enhance,napi_wrap_enhance会在绑定的时候把Native对象大小传给虚拟机,实现及时回收,示例代码如下:

// 通过napi_wrap将ArkTS对象jsThis与C++对象obj绑定
napi_status status = napi_wrap_enhance(env, jsThis, reinterpret_cast<void *>(obj), MyObject::Destructor, false,
                                       nullptr, // finalizeHint
                                       100 * 1024 * 1024, &obj->wrapper_);

常见FAQ

Q:析构Object时调用了napi_remove_wrap,那么对应的FinalizeCallback是否应该被移除?

A:调用napi_remove_wrap的时候,如果封装中关联有finalize回调,HarmonyOS中该导出接口将在移除封装前调用它。