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

Flutter Android应用Firebase Crashlytics莫名崩溃排查求助

问题描述

我开发了一款面向Android平台的Flutter应用,提交至Play Store内部测试及Firebase Robo测试均未发现异常,但Firebase Crashlytics报告了大量来自谷歌设备的崩溃,主要错误为:

Fatal Exception: io.flutter.plugins.firebase.crashlytics.FlutterError:
Null check operator used on a null value. Error thrown null.

查看堆栈跟踪后无法理解其中含义,尝试使用flutter symbolize命令反混淆跟踪信息后仍无法解读:

flutter symbolize -i ./build/symbols/stack.txt -d ./build/symbols/app.android-arm64.symbols |more

不确定这是否是Crashlytics的误报,也不知该如何展开排查,求助解决思路。

完整Crashlytics堆栈跟踪:

# Crashlytics - Stack trace
# Application: app.myapp
# Platform: android
# Version: 1.0.11 (11)
# Issue: 0e1a67110958092c5b5d627bd3bbf313
# Session: 6379F18601E600C92CAE49F9D7E36C5A_DNE_0_v2
# Date: Sun Nov 20 2022 22:21:10 GMT+1300 

Fatal Exception: io.flutter.plugins.firebase.crashlytics.FlutterError: Null check operator used on a null value. Error thrown null.
BuildId: 4269d6000abb454d5f35d98538efa35f
#00 abs 0 virt 00000000005f5f67 _kDartIsolateSnapshotInstructions+0x4717c7
#01 abs 0 virt 00000000005c92de _kDartIsolateSnapshotInstructions+0x444b3e
#02 abs 0 virt 00000000001957da _kDartIsolateSnapshotInstructions+0x1103a
#03 abs 0 virt 000000000019576d _kDartIsolateSnapshotInstructions+0x10fcd
#04 abs 0 virt 00000000001952ee _kDartIsolateSnapshotInstructions+0x10b4e

pool-63-thread-1:
#00 pc 0x0 app.myapp 
#01 pc 0x0 app.myapp (java.util.concurrent.locks.LockSupport.park [LockSupport.java:194])
#02 pc 0x0 app.myapp (java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await [AbstractQueuedSynchronizer.java:2081])
#03 pc 0x0 app.myapp (java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take [ScheduledThreadPoolExecutor.java:1176])
#04 pc 0x0 app.myapp (java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take [ScheduledThreadPoolExecutor.java:905])
#05 pc 0x0 app.myapp (java.util.concurrent.ThreadPoolExecutor.getTask [ThreadPoolExecutor.java:1063])
#06 pc 0x0 app.myapp (java.util.concurrent.ThreadPoolExecutor.runWorker [ThreadPoolExecutor.java:1123])
#07 pc 0x0 app.myapp (java.util.concurrent.ThreadPoolExecutor$Worker.run [ThreadPoolExecutor.java:637])
#08 pc 0x0 app.myapp (java.lang.Thread.run [Thread.java:1012])

pool-79-thread-1:
#00 pc 0x0 app.myapp 
#01 pc 0x0 app.myapp (java.util.concurrent.locks.LockSupport.park [LockSupport.java:194])
#02 pc 0x0 app.myapp (java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await [AbstractQueuedSynchronizer.java:2081])
#03 pc 0x0 app.myapp (java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take [ScheduledThreadPoolExecutor.java:1176])
#04 pc 0x0 app.myapp (java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take [ScheduledThreadPoolExecutor.java:905])
#05 pc 0x0 app.myapp (java.util.concurrent.ThreadPoolExecutor.getTask [ThreadPoolExecutor.java:1063])
#06 pc 0x0 app.myapp (java.util.concurrent.ThreadPoolExecutor.runWorker [ThreadPoolExecutor.java:1123])
#07 pc 0x0 app.myapp (java.util.concurrent.ThreadPoolExecutor$Worker.run [ThreadPoolExecutor.java:637])
#08 pc 0x0 app.myapp (java.lang.Thread.run [Thread.java:1012])

.
.
.

ScionFrontendApi:
#00 pc 0x0 app.myapp 
#01 pc 0x0 app.myapp (java.util.concurrent.locks.LockSupport.parkNanos [LockSupport.java:234])
#02 pc 0x0 app.myapp (java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos [AbstractQueuedSynchronizer.java:2123])
#03 pc 0x0 app.myapp (java.util.concurrent.LinkedBlockingQueue.poll [LinkedBlockingQueue.java:458])
#04 pc 0x0 app.myapp (java.util.concurrent.ThreadPoolExecutor.getTask [ThreadPoolExecutor.java:1062])
#05 pc 0x0 app.myapp (java.util.concurrent.ThreadPoolExecutor.runWorker [ThreadPoolExecutor.java:1123])
#06 pc 0x0 app.myapp (java.util.concurrent.ThreadPoolExecutor$Worker.run [ThreadPoolExecutor.java:637])
#07 pc 0x0 app.myapp (java.lang.Thread.run [Thread.java:1012])

pool-146-thread-1:
#00 pc 0x0 app.myapp 
#01 pc 0x0 app.myapp (java.util.concurrent.locks.LockSupport.park [LockSupport.java:194])
#02 pc 0x0 app.myapp (java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await [AbstractQueuedSynchronizer.java:2081])
#03 pc 0x0 app.myapp (java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take [ScheduledThreadPoolExecutor.java:1176])
#04 pc 0x0 app.myapp (java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take [ScheduledThreadPoolExecutor.java:905])
#05 pc 0x0 app.myapp (java.util.concurrent.ThreadPoolExecutor.getTask [ThreadPoolExecutor.java:1063])
#06 pc 0x0 app.myapp (java.util.concurrent.ThreadPoolExecutor.runWorker [ThreadPoolExecutor.java:1123])
#07 pc 0x0 app.myapp (java.util.concurrent.ThreadPoolExecutor$Worker.run [ThreadPoolExecutor.java:637])
#08 pc 0x0 app.myapp (java.lang.Thread.run [Thread.java:1012])

pool-88-thread-1:
#00 pc 0x0 app.myapp 
#01 pc 0x0 app.myapp (java.util.concurrent.locks.LockSupport.park [LockSupport.java:194])
#02 pc 0x0 app.myapp (java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await [AbstractQueuedSynchronizer.java:2081])
#03 pc 0x0 app.myapp (java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take [ScheduledThreadPoolExecutor.java:1176])
#04 pc 0x0 app.myapp (java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take [ScheduledThreadPoolExecutor.java:905])
#05 pc 0x0 app.myapp (java.util.concurrent.ThreadPoolExecutor.getTask [ThreadPoolExecutor.java:1063])
#06 pc 0x0 app.myapp (java.util.concurrent.ThreadPoolExecutor.runWorker [ThreadPoolExecutor.java:1123])
#07 pc 0x0 app.myapp (java.util.concurrent.ThreadPoolExecutor$Worker.run [ThreadPoolExecutor.java:637])
#08 pc 0x0 app.myapp (java.lang.Thread.run [Thread.java:1012])

pool-102-thread-1:
#00 pc 0x0 app.myapp 
#01 pc 0x0 app.myapp (java.util.concurrent.locks.LockSupport.park [LockSupport.java:194])
#02 pc 0x0 app.myapp (java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await [AbstractQueuedSynchronizer.java:2081])
#03 pc 0x0 app.myapp (java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take [ScheduledThreadPoolExecutor.java:1176])
#04 pc 0x0 app.myapp (java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take [ScheduledThreadPoolExecutor.java:905])
#05 pc 0x0 app.myapp (java.util.concurrent.ThreadPoolExecutor.getTask [ThreadPoolExecutor.java:1063])
#06 pc 0x0 app.myapp (java.util.concurrent.ThreadPoolExecutor.runWorker [ThreadPoolExecutor.java:1123])
#07 pc 0x0 app.myapp (java.util.concurrent.ThreadPoolExecutor$Worker.run [ThreadPoolExecutor.java:637])
#08 pc 0x0 app.myapp (java.lang.Thread.run [Thread.java:1012])
排查解决思路
  • 先确认是否为Crashlytics误报:查看崩溃的设备明细,看是否集中在特定谷歌设备/Android版本;统计崩溃发生的场景(如后台运行、特定操作后),如果大量不同用户出现相同崩溃,基本可以排除误报。
  • 修复符号化失败问题:
    • 确保符号文件与崩溃版本的APK完全匹配(Flutter编译时生成的symbols文件需对应同一版本的release包);
    • 直接在Firebase控制台的Crashlytics模块上传符号文件,避免本地命令行操作的误差;
    • 编译release包时,使用flutter build apk --split-per-abi命令生成对应架构的符号文件,保证符号与设备架构匹配。
  • 主动复现Null check崩溃:
    • 全局搜索代码中所有!操作符,重点检查异步操作(如Future返回null、网络请求失败)、平台通道调用(Android原生返回null)、状态管理中的可空变量;
    • 使用谷歌Pixel系列模拟器/实体设备测试,模拟低内存、网络不稳定、后台切换等边缘场景;
    • 开启Flutter严格空安全模式,在main.dart中添加错误捕获逻辑,或直接用flutter run --release在本地测试release版本(debug版本的空检查逻辑与release存在差异)。
  • 补充日志定位上下文:在可能出现null的关键节点添加日志,发布带日志的测试版本到内部测试,让Crashlytics收集更多崩溃前的变量值和操作路径。
  • 排查第三方依赖兼容性:检查与谷歌服务、原生交互相关的依赖库,尝试暂时禁用部分依赖,验证崩溃是否消失,定位问题依赖。
  • 处理线程相关问题:堆栈中显示多个线程池处于等待状态,但需确认崩溃是否发生在Isolate等后台线程的Dart代码中,可在Isolate内添加错误捕获逻辑,避免未处理的空检查错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 04:40:40