Android应用运行2天自动关闭无常规崩溃,报JNI弱全局引用表溢出错误
Android常驻应用JNI弱全局引用溢出崩溃解决
问题定位
从给出的Native崩溃日志可以确认,崩溃核心原因是JNI弱全局引用表溢出,ART虚拟机为每个应用分配的弱全局引用上限为51200,引用数量达到上限后会主动触发abort杀死进程。该崩溃属于Native层直接触发的进程终止,因此Java层不会捕获到常规异常日志。
从调用栈回溯可以看到,溢出的触发点来自系统WebView组件的JNI调用。
崩溃日志
Fatal signal 6 (SIGABRT), code -6 (SI_TKILL) in tid 30752 (llay.myapp), pid 30752 (llay.myapp) 2021-08-21 00:14:47.663 29579-29579/? A/DEBUG: * * * * * * * * * * * * * * * * 2021-08-21 00:14:47.664 29579-29579/? A/DEBUG: Build fingerprint: 'Amlogic/faraday/faraday:9/PPR1.180610.011/20191021:userdebug/test-keys' 2021-08-21 00:14:47.664 29579-29579/? A/DEBUG: Revision: '0' 2021-08-21 00:14:47.664 29579-29579/? A/DEBUG: ABI: 'arm' 2021-08-21 00:14:47.664 29579-29579/? A/DEBUG: pid: 30752, tid: 30752, name: llay.myapp >>> com.foo.myapp <<< 2021-08-21 00:14:47.664 29579-29579/? A/DEBUG: signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- 2021-08-21 00:14:47.664 29579-29579/? A/DEBUG: Abort message: 'java_vm_ext.cc:662] JNI ERROR (app bug): weak global reference table overflow (max=51200)weak global reference table dump:' 2021-08-21 00:14:47.664 29579-29579/? A/DEBUG: r0 00000000 r1 00007820 r2 00000006 r3 af663918 2021-08-21 00:14:47.664 29579-29579/? A/DEBUG: r4 00007820 r5 00007820 r6 bbdd51a4 r7 0000010c 2021-08-21 00:14:47.664 29579-29579/? A/DEBUG: r8 0000000b r9 bbdd5211 r10 000008b4 r11 bbdd5210 2021-08-21 00:14:47.664 29579-29579/? A/DEBUG: ip 00000041 sp bbdd5190 lr af5f20e5 pc af5e9e72 2021-08-21 00:14:47.672 29579-29579/? A/DEBUG: backtrace: 2021-08-21 00:14:47.672 29579-29579/? A/DEBUG: #00 pc 0001ce72 /system/lib/libc.so (abort+62) 2021-08-21 00:14:47.672 29579-29579/? A/DEBUG: #01 pc 00356e7f /system/lib/libart.so (art::Runtime::Abort(char const*)+798) 2021-08-21 00:14:47.672 29579-29579/? A/DEBUG: #02 pc 000071c7 /system/lib/libbase.so (android::base::LogMessage::~LogMessage()+502) 2021-08-21 00:14:47.672 29579-29579/? A/DEBUG: #03 pc 00236f6b /system/lib/libart.so (art::JavaVMExt::AddWeakGlobalRef(art::Thread*, art::ObjPtr<art::mirror::Object>)+198) 2021-08-21 00:14:47.672 29579-29579/? A/DEBUG: #04 pc 002b0d41 /system/lib/libart.so (art::JNI::NewWeakGlobalRef(_JNIEnv*, _jobject*)+432) 2021-08-21 00:14:47.672 29579-29579/? A/DEBUG: #05 pc 014c1b25 /system/app/webview/webview.apk (offset 0x780000)
排查方向
- 检查应用是否存在高频创建、销毁WebView实例的逻辑,常驻应用长期运行下,每次WebView创建遗留的未释放弱引用会逐步积累,直到触达51200的上限
- 核查应用内自定义JNI代码,是否存在调用
NewWeakGlobalRef创建弱全局引用后,未配套调用DeleteWeakGlobalRef释放的问题,即使单次泄漏量很小,长期运行也会累计到阈值 - 确认WebView相关配套对象(如JsInterface实例、WebSettings、WebView关联的上下文对象)是否存在异常持有,导致WebView native层的弱引用无法被GC回收
解决方案
- WebView复用优化:避免频繁创建销毁WebView,改用实例池复用WebView实例;页面退出时主动调用
WebView.destroy(),同时将WebView从父布局中移除,切断上下文引用链路 - 多进程隔离:Android 9及以上系统可开启WebView多进程模式,将WebView运行在独立进程中,即使WebView触发崩溃也不会杀死主进程,不影响常驻核心功能
- JNI代码规范:所有自定义JNI逻辑中,创建的弱全局引用必须在生命周期结束时主动释放,杜绝引用泄漏
- 泄漏检测:可通过
adb shell dumpsys meminfo 应用包名命令实时查看JNI引用数量变化,定位泄漏触发的具体场景,也可配合LeakCanary排查Java层对象泄漏
内容的提问来源于stack exchange,提问作者Leons
相关产品推荐
相关产品推荐

