安卓稳定性之crash详解

目录

  • 前言
  • 一、Crash 的基本原理
  • 二、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 问题分析以及解决


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/42061.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

p11函数和递归

递归与迭代 求n的阶乘。&#xff08;不考虑溢出&#xff09; int Fac1(int n) {int i0;int ret1;for(i1;i<n;i){ret*i;}return ret; } int main(){//求n的阶乘int n0;int ret0;scanf("%d",&n);retFac1(n);printf("%d\n",ret);return 0; } int Fac…

什么是激光导航和视觉导航技术

激光导航和视觉导航技术是现代导航系统中的两种重要技术&#xff0c;它们在多个领域&#xff0c;如扫地机器人、无人机、机器人导航等中都有广泛应用。以下是对这两种技术的详细介绍&#xff1a; 一、激光导航技术 1. 定义与原理 激光导航技术是一种利用激光束进行精确测量和…

ChatGPT:||是短路运算符,那么|、、是什么?

ChatGPT&#xff1a;||是短路运算符&#xff0c;那么|、&、&&是什么? 在Java中&#xff0c;逻辑运算符&&和||是短路逻辑运算符&#xff0c;而&和|是非短路逻辑运算符。 && 和 || 是短路逻辑运算符。当使用这些运算符时&#xff0c;如果第一个…

解决 Docker 容器镜像拉取难题:全面指南

一、引言 在使用 Docker 容器的过程中&#xff0c;经常会遇到镜像拉取慢甚至无法下载的问题&#xff0c;这给开发和部署工作带来了不小的困扰。本文将深入探讨这一问题的原因&#xff0c;并提供多种有效的解决方案。 二、问题原因分析 网络限制 本地网络带宽不足或存在网络拥…

unity知识点 专项四 一文彻底说清楚(锚点(anchor)、中心点(pivot)、位置(position)之间的关系)

一 概述 想要使UI控件在屏幕中达到正确的显示效果&#xff0c;比如自适应屏幕尺寸、固定边距等等&#xff0c;首先要理清楚几个基本概念和设置&#xff1a;锚点(anchor)、中心点(pivot)、位置(position)、UI缩放模式、父物件的transform设置 二 Anchor、Pivot与Position 2…

网络连接线相关问题

问题1&#xff1b; 直通线为什么两头都是T568B&#xff1f;是否可以两台T5568A&#xff1f;或者任意线序&#xff0c;只需两头一致&#xff1f; 不行&#xff0c;施工规范规定。&#xff08;原因&#xff1b;网线最长距离100m&#xff0c;实际用起来要把网线包管&#xff0c;走…

【分布式系统】Filebeat+Kafka+ELK 的服务部署

目录 一.实验准备 二.配置部署 Filebeat 三.配置Logstash 四.验证 一.实验准备 结合之前的博客中的实验 主机名ip地址主要软件es01192.168.80.101ElasticSearches02192.168.80.102ElasticSearches03192.168.80.103ElasticSearch、Kibananginx01192.168.80.104nginx、Logs…

iperf3: error - unable to connect to server: No route to host

1.确认iperf3版本是否统一。 2.确认防火墙是否关闭。 关闭防火墙 : systemctl stop firewalld 查看防火墙状态: systemctl status firewalld 3.重新建起链接

Java进阶----接口interface

接口 接口概述 接口是一种规范&#xff0c;使用接口就代表着要在程序中制定规范. 制定规范可以给不同类型的事物定义功能&#xff0c;例如&#xff1a; 利用接口&#xff0c;给飞机、小鸟制定飞行规范&#xff0c;让其都具备飞行的功能&#xff1b;利用接口&#xff0c;给鼠…

SMU Summer 2024 Contest Round 1

A.Hcode OnlineJudge 给出一个N面骰子和整数K&#xff0c;掷出1-N之间的每个数的概率相同&#xff0c;每次掷出一次&#xff0c;记为成绩&#xff0c;若成绩小于K&#xff0c;则开始抛硬币&#xff0c;硬币朝上则数翻倍&#xff0c;反之则为0&#xff0c;概率都为0.5。当数大于…

自动驾驶算法———车道检测(一)

“ 在本章中&#xff0c;我将指导您构建一个简单但有效的车道检测管道&#xff0c;并将其应用于Carla 模拟器中捕获的图像。管道将图像作为输入&#xff0c;并产生车道边界的数学模型作为输出。图像由行车记录仪&#xff08;固定在车辆挡风玻璃后面的摄像头&#xff09;捕获。…

【ZIP压缩大揭秘】轻松掌握ZIP分卷压缩包的高效解压秘籍!

在这个信息爆炸的时代&#xff0c;文件大小常常成为我们分享与存储的绊脚石。幸运的是&#xff0c;ZIP分卷压缩技术如同一把钥匙&#xff0c;巧妙地将庞然大物分解成小巧易管理的部分。但面对这一串分卷压缩包&#xff0c;你是否也曾迷茫于如何高效解压&#xff0c;恢复文件的完…

解码Python字符串:‘r‘、‘b‘、‘u‘和‘f‘前缀的全面指南

&#x1f4d6; 正文 1 字符串前加’r’ 表示原始字符串&#xff0c;消除转义 print(abc\nde) # abc # deprint(rabc\nde) # abc\nde在下面这个列子中&#xff0c;如果不在路径字符串前面加r那么&#xff0c;路径中的空格就会出现问题 print(rD:\01 programming\09python\py…

全志A527 T527 cat /proc/cupinfo没有Serial问题

1.前言 我们有些客户是使用cpuinfo节点去获取系统的cpuid的,如下: cat /proc/cupinfo processor : 0 BogoMIPS : 48.00 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp CPU impleme…

系统吃swap问题排查

目录 背景 问题 分析并解决 1.控制线程数 2.更换IO组件 3.Linux进程信息文件分析 总结加餐 参考文档 背景 隔壁业务组系统是简单的主从结构&#xff0c;写索引的服务(主)叫primary&#xff0c; 读索引并提供搜索功能的服务(从)叫replica。业务线同步数据并不是平滑的&…

离散化及其在 Pandas 中的实现方法

目录 1.什么是离散化&#xff1f; 2.离散化类型 3.示例代码 3.1连续变量离散化 3.2定性变量离散化 4.运行结果 4.1连续变量离散化 4.2定性变量离散化 1.什么是离散化&#xff1f; 离散化是将连续数据或分类数据转换为离散类别的过程&#xff0c;方便后续的数据分析和机…

static的理论学习

在说到static之前&#xff0c;需要先明确变量类型&#xff1a; 而在聊到变量类型之前我们可以将变量的两个属性好好学一学 变量的两个属性 作用域&#xff08;scope&#xff09;&#xff1a; 从内存的角度来看&#xff0c;就是变量存放在栈&#xff08;stack&#xff09;中&…

在 JavaScript 中,??(双问号运算符)和 ?.(可选链运算符)区别

在 JavaScript 中&#xff0c;??&#xff08;双问号运算符&#xff09;和 ?.&#xff08;可选链运算符&#xff09;是两种不同的运算符&#xff0c;用于处理不同的情况&#xff1a; 双问号运算符 (??): ?? 运算符是空值合并运算符&#xff08;Nullish Coalescing Oper…

Android C++系列:Linux进程(一)

1. 进程概念 我们知道,每个进程在内核中都有一个进程控制块(PCB)来维护进程相关的信 息,Linux内核的进程控制块是task_struct结构体。现在我们全面了解一下其中都有哪 些信息。 进程id。系统中每个进程有唯一的id,在C语言中用pid_t类型表示,其实就是一个非 负整数。进程的…

TypeError: Cannot read properties of null (reading ‘nextSibling‘)

做项目用的Vue3Vite, 在画静态页面时&#xff0c;点击菜单跳转之后总是出现如下报错&#xff0c;百思不得其解。看了网上很多回答&#xff0c;也没有解决问题&#xff0c;然后试了很多方法&#xff0c;最后竟然发现是template里边没有结构的原因。。。 原来我的index.vue是这样…