You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Chakra Core无内存问题取值及回调GC崩溃的技术问询

解答Chakra Core JSRT托管中的内存与回调GC问题

我来帮你拆解你遇到的几个核心问题,结合ChakraCore JSRT的托管特性逐一说明:

一、回调被GC回收导致AV崩溃的核心原因

你遇到的访问违例(AV)问题,本质是C#委托被垃圾回收(GC)后,ChakraCore原生层仍持有无效指针。

C#的JsNativeFunction委托是引用类型,如果它只是作为局部变量传递给JsCreateFunction,当方法执行完毕后,这个委托就失去了强引用,GC会在后续回收周期里释放它的内存。但ChakraCore的原生运行时还保留着这个委托的原生指针,当JS侧调用该函数时,就会访问已经被回收的内存,触发AV错误。

解决方法:强引用保留委托

必须把委托对象作为类的成员变量(而非局部变量)保存,确保GC无法回收它:

// 类级别字段,强引用保存委托
private JsNativeFunction _nativeFunctionDelegate;

private void RegisterNativeFunction()
{
    // 赋值给成员变量,保留强引用
    _nativeFunctionDelegate = nativeFunction;
    JsCreateFunction(_nativeFunctionDelegate, IntPtr.Zero, out var func);
    // 后续将func暴露给JS环境...
}

private static JavaScriptValue nativeFunction(JavaScriptValue callee, bool isConstructCall, JavaScriptValue[] arguments, ushort argumentCount, IntPtr callbackData)
{
    // 你的函数逻辑
    return JavaScriptValue.Undefined;
}

二、示例中返回脚本结果两倍值的逻辑

那个示例里的“返回两倍值”逻辑,其实是演示JS值的引用计数管理,而非业务需求。

ChakraCore的JavaScriptValue基于引用计数机制:

  1. 当你从JS环境获取一个值时,它的引用计数会自动增加
  2. 当你不再需要这个值时,必须调用JsRelease减少引用计数,否则会导致内存泄漏
  3. 如果返回值的引用计数被提前释放,就会出现悬空指针问题

示例中返回两倍值的操作,实际是手动管理引用的示范:先获取脚本结果,调用JsAddRef确保引用计数正确,处理后再返回,避免值被意外释放。你不需要照搬“两倍值”的逻辑,但必须记住:所有从JS侧获取的JavaScriptValue,都要正确处理引用计数,尤其是在跨托管/原生边界传递时。

三、runScriptDelegate的回调触发方式

runScriptDelegate是ChakraCore用于异步脚本执行的回调调度机制:

  • 当你调用JsRunScriptAsync这类异步API时,ChakraCore的原生运行时会在后台线程执行脚本
  • 脚本执行完成(或遇到错误、异步暂停)时,运行时会主动触发runScriptDelegate回调,把执行结果、错误信息传递给托管层
  • 回调的触发时机由ChakraCore的事件循环调度,不需要你手动调用

和原生函数委托一样,runScriptDelegate也必须被强引用保存,否则同样会因为GC回收导致AV错误。

四、zxcvbn引擎内存取值的验证建议

针对你开发的zxcvbn执行引擎,建议做以下内存检查:

  • 每次从JS函数获取返回值时,先调用JsAddRef增加引用计数,确保在处理过程中值不会被释放
  • 处理完值后,务必调用JsRelease减少引用计数,避免内存泄漏
  • 所有注册给ChakraCore的委托(包括原生函数、异步回调),都要作为类成员变量保留强引用,不要用局部变量

内容的提问来源于stack exchange,提问作者MichaelChan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:46:54