问题描述
模拟器中任何情况下,只要有页面加了键盘组件(不管键盘是否显示),都会在模拟器重装应用后(不初始化)再次打开该页面时崩溃。首次安装启动正常。
复现步骤
- 首次启动应用 → 进入带 InputMethod 键盘的页面 → 正常
- 按返回键退出页面
- 重装应用(adb install -r,不清数据)
- 再次启动 → 进入同一页面 → 崩溃
关键日志
第一轮(成功)
115.657 AMS attach
115.844 quickapp screen: shape=rect
127.967 push /pages/search
128.022 InputMethod uid:74 init/build
128.058 Page ready
132.994 stop(back 键)
133.303 Activity onDestroy
133.304 PageNavigator::clearAll
133.340 flush tasks
133.342 jse_dump_memory_status
133.353 App Closed
Destroy 后存在 Object Leak
[133.342800] Object leaks:
ADDRESS REFS SHRF PROTO CLASS PROPS
0x40c52910 1 0* 0x40666590 Function { length: 1, name: 1"bound watchMaxLengthPropsChange" }
bound watchMaxLengthPropsChange 是 InputMethod 组件中 maxlength prop 的 watcher 绑定的 bound 函数,Destroy 后 REFS=1 未释放。
第二轮(崩溃,距上一轮 close 仅 230ms)
133.589 AMS 再次 start com.watch.dic
135.425 push /pages/search
135.480 js_dom_create_component=input-method uid:180
135.4807 arm_dataabort PC:0080e508 DFAR:00000011
崩溃栈
std::__1::__tree<...PropsCheckType...>::destroy
JsSubComponentFactory::createPropDescriptionFromObject+0x9b
根因分析
JsSubComponentFactory 内部维护了一个静态/全局的 prop description 缓存(map<string, PropsCheckType>),该缓存在 app restart 后存活。
- 第一轮运行:缓存中创建了包含 bound watchMaxLengthPropsChange(JSValue)的 PropsCheckType 条目
- Destroy 时:bound 函数泄漏(REFS=1),但 C++ 层的 map 缓存未清理
- 第二轮运行:QuickJS 新 runtime 启动,但该静态 map 中的 JSValue 指向上一轮 runtime 的已释放堆块
- 读取缓存 → 野指针解引用 → DFAR=0x11(接近 NULL 的低地址 Data Abort)
关联现象
- DFAR 为极低地址(0x11/0x12),符合 QuickJS NaN-boxing 无效 handle 解引用的特征
- 首次安装不崩(缓存为空,从头创建)
- DFAR=0x12 在不同 build 中偶尔出现(偏移不同,本质同类)
建议修复方向
- InputMethod.ux 侧:移除 $watch/$unwatch 模式,改用直接 prop 初始化,消除 bound 函数泄漏
- JsSubComponentFactory 侧:在 Application::destroy 或 FeatureManagerQjs 析构时清除静态 prop description 缓存
- 框架侧:将 JsSubComponentFactory 改为 per-runtime 实例,而非 static/全局单例
问题描述
模拟器中任何情况下,只要有页面加了键盘组件(不管键盘是否显示),都会在模拟器重装应用后(不初始化)再次打开该页面时崩溃。首次安装启动正常。
复现步骤
关键日志
第一轮(成功)
Destroy 后存在 Object Leak
bound watchMaxLengthPropsChange 是 InputMethod 组件中 maxlength prop 的 watcher 绑定的 bound 函数,Destroy 后 REFS=1 未释放。
第二轮(崩溃,距上一轮 close 仅 230ms)
崩溃栈
根因分析
JsSubComponentFactory 内部维护了一个静态/全局的 prop description 缓存(map<string, PropsCheckType>),该缓存在 app restart 后存活。
关联现象
建议修复方向