目錄
- 前言
- 一、Crash 的基本原理
- 二、Crash 分析思路
- 三、實例分析
- 四、預防措施
- 五、參考鏈接
前言
在開發和測試 Android 應用程序時,遇到應用程序崩潰是很常見的情況。 Android 崩潰指的是應用程序因為異常或錯誤而無法正常執行,并且導致應用強制關閉。
一、Crash 的基本原理
Android 應用運行在 Dalvik/ART 虛擬機中,當應用中出現未處理的異常時,虛擬機會終止應用的進程,導致應用崩潰。通常, Android Crash 可以分為以下幾種類型:
- 空指針異常(NullPointerException) :當代碼嘗試訪問一個空對象引用時,會拋
出該異常。 - 數組越界異常(ArrayIndexOutOfBoundsException) :當代碼嘗試訪問超過數組
邊界范圍的元素時,會拋出該異常。 - 類轉換異常(ClassCastException) :當代碼嘗試將一個對象轉換成不兼容的類型
時,會拋出該異常。 - 內存泄漏(Memory Leaks) :當應用程序持有對某個對象的引用,但該對象已經
不再需要并且無法被釋放回收時,就發生了內存泄漏。 - 資源未釋放(Resource Not Released) :在使用一些需要手動管理資源(如數據
庫連接、文件流等)的情況下,如果沒有正確釋放這些資源,在長時間運行后可能
導致系統資源耗盡并觸發崩潰
二、Crash 分析思路
-
收集 Crash 信息
要分析 Crash,首先需要收集相關的信息。我們可以通過以下途徑獲取 Crash 信息:
? Android Studio 的 Logcat
? 第三方 Crash 收集工具(如: Firebase Crashlytics, Bugly 等)
? 操作系統提供的日志工具(如: adb logcat) -
分析 Crash 日志
分析 Crash 日志是定位問題的關鍵。我們需要關注以下幾個方面的信息:
? 異常類型: Java 層異常、 Native 層異常或 ANR
? 異常原因:例如空指針異常、數組越界等
? 堆棧信息:從堆棧信息中,我們可以定位到具體的代碼行數 -
重現崩潰
為了更好地理解問題,我們需要嘗試重現崩潰。這可以幫助我們確定崩潰發生的條件和場
景。重現崩潰還可以幫助我們驗證解決方案是否有效。 -
調試和測試
在確定崩潰原因后,我們需要進行調試和測試。這可以幫助我們驗證解決方案是否有效,
并確保它不會引入新的問題。一般 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。
修改方案如下:
四、預防措施
為了減少應用程序崩潰的風險,可以采取以下預防措施:
- 良好的異常處理:在關鍵代碼塊中使用 try-catch 語句來捕獲和處理可能拋出的異常。這樣可以避免應用程序因為未處理的異常而崩潰,并提供更友好的用戶體驗。
- 合理地使用空值檢查:確保在訪問對象之前進行適當的空值檢查,以避免觸發空指針異常。
- 正確釋放資源:對于需要手動管理資源(如數據庫連接、文件流等),始終確保及時釋放這些資源,以避免資源泄漏和系統負載過高導致崩潰。
- 謹慎使用第三方庫:選擇可靠且經過廣泛測試的第三方庫,并仔細閱讀其文檔和源代碼。不推薦使用已知存在問題或長期無更新支持的庫。
- 定期進行性能優化和內存管理:通過減少內存占用、優化算法、限制并發線程數等方法,改善應用程序性能并減少崩潰風險。
- 多渠道測試與發布前驗證:在發布前進行全面測試,并覆蓋各種設備、操作系統版本和網絡條件下運行應用程序的場景。這有助于發現并修復潛在的崩潰問題。
五、參考鏈接
Android中Crash原理及監控處理
Android app 崩潰 & Crash 分析
Android Crash 問題分析以及解決