在 iOS 上强制对 JavaScriptCore 虚拟机进行垃圾回收

Force garbage collection of JavaScriptCore virtual machine on iOS

有什么方法可以强制 iOS(或 Mac OS)JavaScriptCore VM 垃圾收集器到 运行?我只需要它来测试内存泄漏,所以 private API 就可以了。

使用 JSBase.h 中的以下函数:

/*!
@function JSGarbageCollect
@abstract Performs a JavaScript garbage collection.
@param ctx The execution context to use.
@discussion JavaScript values that are on the machine stack, in a register,
 protected by JSValueProtect, set as the global object of an execution context,
 or reachable from any such value will not be collected.

 During JavaScript execution, you are not required to call this function; the
 JavaScript engine will garbage collect as needed. JavaScript values created
 within a context group are automatically destroyed when the last reference
 to the context group is released.
*/
JS_EXPORT void JSGarbageCollect(JSContextRef ctx);

您可以从 JSContext 中获取 JSContextRef,只读 JSGlobalContextRef 属性。

更新

我发现了 WebKit 的下一个变化 - bugs.webkit.org/show_bug.cgi?id=84476:

JSGarbageCollect should not synchronously call collectAllGarbage(). Instead, it should notify the GCActivityCallback that it has abandoned an object graph, which will set the timer to run at some point in the future that JSC can decide according to its own policies.

这解释了为什么以前的解决方案无法按预期工作。

深入挖掘 WebKit 资源,我发现了另一种有趣的方法。请尝试以下代码:

JS_EXPORT void JSSynchronousGarbageCollectForDebugging(JSContextRef ctx);

@interface JSContext (GarbageCollection)

-(void)garbageCollect {
    JSSynchronousGarbageCollectForDebugging(self.JSGlobalContextRef);
}

@end

之后只需在您的 JSContext 实例上调用 garbageCollect 方法。我已经在 iOS 上本地试过了,它似乎有效。