求助定位Android应用Java数组越界崩溃来源
定位并修复
IndexOutOfBoundsException: Index 90 out of bounds for length 0崩溃 先明确日志里的关键信息
你贴的日志里,Thread.java:1012和ArrayList.java:434都是JDK系统类的代码,不是你的应用代码。崩溃的本质是:你的代码调用了ArrayList.get(90),但这个ArrayList是空的(长度为0),但因为代码被混淆(ProGuard/R8),Google Play Console无法显示你的调用代码位置。
核心解决步骤:恢复混淆后的堆栈信息
你看不到自己代码的原因是release包开启了代码混淆,必须上传映射文件才能反混淆日志:
- 找到你打包release版本时生成的mapping.txt文件,路径一般是
app/build/outputs/mapping/release/mapping.txt - 登录Google Play Console,进入你的应用 → 「质量」→「崩溃与ANR」→ 右上角「设置」→「上传映射文件」,选择对应的mapping文件上传(注意每个release包的mapping文件唯一,要对应版本)
- 上传后,刷新崩溃日志,就能看到你自己的类、方法和代码行号,直接定位问题位置
其他辅助排查方法
如果暂时无法上传映射文件,试试这些方法:
临时关闭混淆打包测试
在build.gradle的release构建配置里关闭混淆:buildTypes { release { minifyEnabled false shrinkResources false // 注释掉proguardFiles相关配置 } }打一个这样的release包,用内部测试渠道分发,复现崩溃后就能拿到完整的未混淆堆栈。
全局捕获异常,记录上下文
不用到处加try/catch,给全局线程设置异常处理器,捕获崩溃时的更多细节:// 在Application的onCreate()里初始化 Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> { Log.e("CrashDebug", "崩溃线程: " + thread.getName()); // 可以额外记录当前应用中所有可疑ArrayList的大小(如果能拿到引用的话) // 比如:if (myList != null) Log.e("CrashDebug", "myList大小: " + myList.size()); // 最后交给默认处理器处理崩溃 throwable.printStackTrace(); });这样拿到的本地日志会包含更多上下文,帮你缩小范围。
针对性排查空列表场景
崩溃信息明确是空列表访问索引90,重点查这些场景:- 是否有异步加载数据的逻辑,UI线程在数据加载完成前就访问了列表
- 哪里调用了
ArrayList.clear(),但后续没有检查列表是否为空就调用get() - 是否有列表初始化后,因为逻辑错误没填充数据就被使用
为什么try/catch没效果?
你加的try/catch没覆盖到崩溃发生的代码块,或者崩溃发生在你没监控的子线程里,全局异常处理器能解决这个问题。
内容的提问来源于stack exchange,提问作者Jason W
相关产品推荐
相关产品推荐

