安卓稳定性之crash详解


前言

在开发和测试 Android 应用程序时,遇到应用程序崩溃是很常见的情况。 Android 崩溃指的是应用程序因为异常或错误而无法正常执行,并且导致应用强制关闭。


一、Crash 的基本原理

Android 应用运行在 Dalvik/ART 虚拟机中,当应用中出现未处理的异常时,虚拟机会终止应用的进程,导致应用崩溃。通常, Android Crash 可以分为以下几种类型:

  1. 空指针异常(NullPointerException) :当代码尝试访问一个空对象引用时,会抛
    出该异常。
  2. 数组越界异常(ArrayIndexOutOfBoundsException) :当代码尝试访问超过数组
    边界范围的元素时,会抛出该异常。
  3. 类转换异常(ClassCastException) :当代码尝试将一个对象转换成不兼容的类型
    时,会抛出该异常。
  4. 内存泄漏(Memory Leaks) :当应用程序持有对某个对象的引用,但该对象已经
    不再需要并且无法被释放回收时,就发生了内存泄漏。
  5. 资源未释放(Resource Not Released) :在使用一些需要手动管理资源(如数据
    库连接、文件流等)的情况下,如果没有正确释放这些资源,在长时间运行后可能
    导致系统资源耗尽并触发崩溃

二、Crash 分析思路

  1. 收集 Crash 信息
    要分析 Crash,首先需要收集相关的信息。我们可以通过以下途径获取 Crash 信息:
    • Android Studio 的 Logcat
    • 第三方 Crash 收集工具(如: Firebase Crashlytics, Bugly 等)
    • 操作系统提供的日志工具(如: adb logcat)

  2. 分析 Crash 日志
    分析 Crash 日志是定位问题的关键。我们需要关注以下几个方面的信息:
    • 异常类型: Java 层异常、 Native 层异常或 ANR
    • 异常原因:例如空指针异常、数组越界等
    • 堆栈信息:从堆栈信息中,我们可以定位到具体的代码行数

  3. 重现崩溃
    为了更好地理解问题,我们需要尝试重现崩溃。这可以帮助我们确定崩溃发生的条件和场
    景。重现崩溃还可以帮助我们验证解决方案是否有效。

  4. 调试和测试
    在确定崩溃原因后,我们需要进行调试和测试。这可以帮助我们验证解决方案是否有效,
    并确保它不会引入新的问题。一般 crash 的问题比较明显,容易找到问题。


三、实例分析

案例:空指针异常

09-22 07:16:41.848 +0000 17248 17248 D AndroidRuntime: Shutting down VM
09-22 07:16:41.848 +0000 17248 17248 E AndroidRuntime: *** FATAL EXCEPTION INSYSTEM PROCESS: main
09-22 07:16:41.848 +0000 17248 17248 E AndroidRuntime: java.lang.NullPointerException: Attempt to read from field 'java.lang.String com.android.server.pm.Settings$VersionInfo.fingerprint' on a null object reference
09-22 07:16:41.848 +0000 17248 17248 E AndroidRuntime: at com.android.server.pm.PackageManagerService.<init>(PackageManagerService.java:7613)
09-22 07:16:41.848 +0000 17248 17248 E AndroidRuntime: at com.android.server.pm.PackageManagerService.main(PackageManagerService.java:7121)
09-22 07:16:41.848 +0000 17248 17248 E AndroidRuntime: at com.android.server.SystemServer.startBootstrapServices(SystemServer.java:1166)
09-22 07:16:41.848 +0000 17248 17248 E AndroidRuntime: at com.android.server.SystemServer.run(SystemServer.java:880)
09-22 07:16:41.848 +0000 17248 17248 E AndroidRuntime: at com.android.server.SystemServer.main(SystemServer.java:613)
09-22 07:16:41.848 +0000 17248 17248 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
09-22 07:16:41.848 +0000 17248 17248 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
09-22 07:16:41.848 +0000 17248 17248 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987)
09-22 07:16:41.850 +0000 17248 17248 E AndroidRuntime: Error reporting crash
09-22 07:16:41.850 +0000 17248 17248 E AndroidRuntime: java.lang.NullPointerException: Attempt to invoke interface method 'void android.app.IActivityManager.handleApplicationCrash(android.os.IBinder,android.app.ApplicationErrorReport$ParcelableCrashInfo)' on a null object reference
09-22 07:16:41.850 +0000 17248 17248 E AndroidRuntime: at com.android.internal.os.RuntimeInit$KillApplicationHandler.uncaughtException(RuntimeInit.java:156)
09-22 07:16:41.850 +0000 17248 17248 E AndroidRuntime: at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1073)
09-22 07:16:41.850 +0000 17248 17248 E AndroidRuntime: at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1068)
09-22 07:16:41.850 +0000 17248 17248 E AndroidRuntime: at java.lang.Thread.dispatchUncaughtException(Thread.java:2200)

分析过程:
(1) Settings$VersionInfo.fingerprint 为空,找到出现问题的代码:
在这里插入图片描述
(2)自己对源码进行分析,发现一个方法,该方法能创建或者找到版本的信息,如果为空
则添加到集合中。而报错的地方,是调用 getInternalVersion(),没有做判空的处理。
在这里插入图片描述
(3)继续跟踪代码, mVersion 是一个集合,通过键值对来获取那个值
在这里插入图片描述
(4)UUID_PRIVATE_INTERNAL 是 null
在这里插入图片描述
(5)猜想空指针异常可能是没有调用 findOrCreateVersion(),没有创建对应的值并且没有
put 到集合中。并且打印了正常能开机的 mVersion 的大小,都是 2。
在这里插入图片描述
修改方案如下:
在这里插入图片描述


四、预防措施

为了减少应用程序崩溃的风险,可以采取以下预防措施:

  1. 良好的异常处理:在关键代码块中使用 try-catch 语句来捕获和处理可能抛出的异常。这样可以避免应用程序因为未处理的异常而崩溃,并提供更友好的用户体验。
  2. 合理地使用空值检查:确保在访问对象之前进行适当的空值检查,以避免触发空指针异常。
  3. 正确释放资源:对于需要手动管理资源(如数据库连接、文件流等),始终确保及时释放这些资源,以避免资源泄漏和系统负载过高导致崩溃。
  4. 谨慎使用第三方库:选择可靠且经过广泛测试的第三方库,并仔细阅读其文档和源代码。不推荐使用已知存在问题或长期无更新支持的库。
  5. 定期进行性能优化和内存管理:通过减少内存占用、优化算法、限制并发线程数等方法,改善应用程序性能并减少崩溃风险。
  6. 多渠道测试与发布前验证:在发布前进行全面测试,并覆盖各种设备、操作系统版本和网络条件下运行应用程序的场景。这有助于发现并修复潜在的崩溃问题。

五、参考链接

Android中Crash原理及监控处理
Android app 崩溃 & Crash 分析
Android Crash 问题分析以及解决


  • 30
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值