1.崩潰分析策略
1.1 android.view.WindowManager$BadTokenException
Unable to add window -- token android.os.BinderProxy@3d86cef3 is not valid; is your activity running?
android.view.ViewRootImpl.setView(ViewRootImpl.java:688)--操盤達人
** [解決方案]**
該異常表示不能添加窗口蚯瞧,通常是所要依附的view已經(jīng)不存在導(dǎo)致的楷力。
[解決方案]:Dialog&AlertDialog琢岩,WindowManager不能正確使用時撼班,經(jīng)常會報出該異常旗扑,原因比較多维哈,幾個常見的場景如下:
1.上一個頁面沒有destroy的時候例隆,之前的Activity已經(jīng)接收到了廣播阔逼。如果此時之前的Activity進行UI層面的操作處理论巍,就會造成crash烛谊。UI層面的刷新,一定要注意時機嘉汰,建議使用set_result來代替廣播的形式進行刷新操作丹禀,避免使用廣播的方式,代碼不直觀且容易出錯鞋怀。
2.Dialog在Actitivty退出后彈出双泪。在Dialog調(diào)用show方法進行顯示時,必須要有一個Activity作為窗口的載體密似,如果Activity被銷毀焙矛,那么導(dǎo)致Dialog的窗口載體找不到。建議在Dialog調(diào)用show方法之前先判斷Activity是否已經(jīng)被銷毀残腌。
3.Service&Application彈出對話框或WindowManager添加view時薄扁,沒有設(shè)置window type為TYPE_SYSTEM_ALERT。需要在調(diào)用dialog.show()方法前添加dialog.getWindow().SetType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)废累。
4.6.0的系統(tǒng)上, (非定制 rom 行為)若沒有給予懸浮窗權(quán)限, 會彈出該問題, 可以通過Settings.canDrawOverlays來判斷是否有該權(quán)限.
5.某些不穩(wěn)定的MIUI系統(tǒng)bug引起的權(quán)限問題邓梅,系統(tǒng)把Toast也當(dāng)成了系統(tǒng)級彈窗,android6.0的系統(tǒng)Dialog彈窗需要用戶手動授權(quán)邑滨,若果app沒有加入SYSTEM_ALERT_WINDOW權(quán)限就會報這個錯日缨。需要加入給app加系統(tǒng)Dialog彈窗權(quán)限,并動態(tài)申請權(quán)限掖看,不滿足第一條會出現(xiàn)沒權(quán)限閃退匣距,不滿足第二條會出現(xiàn)沒有Toast的情況。
1.2 java.util.concurrent.TimeoutException
android.database.BulkCursorToCursorAdaptor.finalize() timed out after 120 seconds
android.os.BinderProxy.transactNative(Native Method)--玉面小色熊
[解決方案]
該異常表示調(diào)用超時哎壳。
[解決方案]:一般是系統(tǒng)在gc時毅待,調(diào)用對象的finalize超時導(dǎo)致,解決辦法:
1.檢查分析finalize的實現(xiàn)為什么耗時較高归榕,修復(fù)它尸红;
2.檢查日志查看GC是否過于頻繁,導(dǎo)致超時,減少內(nèi)容開銷外里,防止內(nèi)存泄露怎爵。
1.3 java.lang.NullPointerException
[解決方案]
該異常表示嘗試去調(diào)用virtual method,使用了一個空對象引用盅蝗,建議您檢查引用的對象是否為空鳖链。
[解決方案]:這種異常通常是調(diào)用一個對象的方法拋出的,凡是調(diào)用一個對象的方法之前墩莫,一定要進行判空或者進行try-catch芙委,這樣基本可以規(guī)避大部分空指針異常。
1.4 java.lang.NumberFormatException
[解決方案]
該異常表示字符串嘗試轉(zhuǎn)換為其他類型出錯狂秦,轉(zhuǎn)換類型異常题山。
[解決方案]:當(dāng)字符串嘗試轉(zhuǎn)換為數(shù)字類型失敗時,拋出該異常故痊。舉例如下:String test = "test123";int result = Integer.parseInt(test);此時由于字符串中含有非數(shù)值字段顶瞳,將會拋出該異常。
1.5 #271 android.database.sqlite.SQLiteDiskIOException
[解決方案]
該異常表示磁盤輸入/輸出錯誤愕秫,可能是數(shù)據(jù)操作太頻繁導(dǎo)致的慨菱。應(yīng)用程序啟動時,調(diào)用RSSDatabase的構(gòu)造函數(shù)戴甩,UI Thread鎖定了你的目標(biāo)的數(shù)據(jù)庫符喝,隨后你又嘗試插入數(shù)據(jù)到被UI線程鎖定的數(shù)據(jù)庫。 將拋出一個異常甜孤,因為db被lock了协饲。
1.6 java.lang.ClassCastException
[解決方案]
該異常表示類型轉(zhuǎn)換異常,通常是因為一個類對象轉(zhuǎn)換為其他不兼容類對象拋出的異常缴川,檢查你要轉(zhuǎn)換的類對象類型茉稠。
[解決方案]:一般在強制類型轉(zhuǎn)換時出現(xiàn),例如如果A向B轉(zhuǎn)換把夸,而A不是B的父類時而线,將產(chǎn)生java.lang.ClassCastException異常。一般建議做這時要使用instanceof做一下類型判斷恋日,再做轉(zhuǎn)換膀篮。[其他場景] :例如使用Recyclerview的itemView中的控件,設(shè)置了LayoutParams岂膳。造成轉(zhuǎn)換異常誓竿。
1.7 java.lang.IllegalStateException: Fragment not attached to Activity
[原因]出現(xiàn)該異常,是因為Fragment的還沒有Attach到Activity時谈截,調(diào)用了如getResource()等筷屡,需要上下文Content的函數(shù)涧偷。
[解決方法] 在調(diào)用需要Context的函數(shù)之前,增加一個判斷isAdded()
1.8 java.lang.ArrayIndexOutOfBoundsException
[原因]
概述:該異常表示數(shù)組越界速蕊。
[解決方案]
這種情況一般要在數(shù)組循環(huán)前做好length判斷,index超出length上限和下限時都會報錯娘赴。舉例如下:一個數(shù)組int test[N]规哲,一共有N個元素分別是test[0]~test[N-1],如果調(diào)用test[N]诽表,將會報錯唉锌。建議讀取時,不要超過數(shù)組的長度(array.length)竿奏。
Android中一種常見情形就是上拉刷新中header也會作為listview的第0個位置袄简,如果判斷失誤很容易造成越界。
[異常情況1]
TextView 中 ellipsize 使用引發(fā) Crash泛啸,該問題為 Android 系統(tǒng) bug绿语,存在于 Android 5.0 及以下設(shè)備,問題描述參考:https://code.google.com/p/android/issues/detail?id=33868
[解決方案]:使用 android:singleLine="true" 代替 android:lines="1" 和 android:maxLines="1"
1.9 java.lang.ClassNotFoundException
[原因]
該異常表示在路徑下候址,找不到指定類吕粹,通常是因為構(gòu)建路徑問題導(dǎo)致的。
[解決方案]
類名是以字符串形式標(biāo)識的岗仑,可信度比較低匹耕,在調(diào)用Class.forName(""),Class.findSystemClass(""),Class.loadClass("")等方法時,找不到類名時將會報錯荠雕。如果找不到的Class是系統(tǒng)Class稳其,那么可能是系統(tǒng)版本兼容,廠家Rom兼容的問題炸卑,找到對應(yīng)的設(shè)備嘗試重現(xiàn)既鞠,解決方法可以考慮更換Api,或用自己實現(xiàn)的Class替代盖文。
如果找不到的Class是應(yīng)用自由Class(含第三方SDK的Class)损趋,可以通過反編譯工具查看對應(yīng)apk中是否真的缺少該Class,再進行定位椅寺,這種往往發(fā)生在:
1.要找的Class被混淆了浑槽,存在但名字變了;
2.要找的Class未被打入Dex返帕,確實不存在桐玻,可能是因為自己的疏忽,或編譯環(huán)境的沖突荆萤;
3.要找的Class確實存在镊靴,但你的Classlorder找不到這個Class铣卡,往往因為這個Classloder是你自實現(xiàn)的(插件化應(yīng)用中常見)。
1.10 java.lang.SecurityException
Requires READ_PHONE_STATE: Neither user 1000 nor current process has android.permission.READ_PHONE_STATE.
[原因]
該異常表示需要讀取電話狀態(tài)偏竟,但沒有權(quán)限煮落。
[解決方案]此類問題一般是未申明權(quán)限導(dǎo)致,建議檢查是否有讀取電話狀態(tài)的權(quán)限踊谋,解決方法:
1.android6.0以下需要在manifest中聲明相應(yīng)的權(quán)限蝉仇;
2.android6.0及以上,在使用時需要動態(tài)申請權(quán)限殖蚕;
1.11 android.content.ReceiverCallNotAllowedException
BroadcastReceiver components are not allowed to register to receive intents
com.bocharov.xposed.fscb.util.EventsReceiver$class.startReceive(SourceFile:46)
[解決方案]
1轿衔、bindService不能在BroadcastReceiver 中調(diào)用,你可以在里面調(diào)用StartService并把要傳遞參數(shù)放到intent中
2睦疫、registerReceiver不能在BroadcastReceiver調(diào)用害驹,可以通過context.getApplicationContext().registerReceiver()
#######1.12 java.lang.IllegalArgumentException
[解決方案]
參數(shù)不匹配異常,通常由于傳遞了不正確的參數(shù)導(dǎo)致蛤育。
常見于:
- Activity宛官、Service狀態(tài)異常;
- 非法URL瓦糕;
- UI線程操作摘刑。
- Fragment中嵌套了子Fragment,F(xiàn)ragment被銷毀刻坊,而內(nèi)部Fragment未被銷毀枷恕,所以導(dǎo)致再次加載時重復(fù),在onDestroyView() 中將內(nèi)部Fragment銷毀即可
1.13 android.os.TransactionTooLargeException
[原因]
Binder傳輸?shù)臄?shù)據(jù)太大導(dǎo)致的異常谭胚。
如果Binder的參數(shù)或返回值太大徐块,不適合的事務(wù)緩沖區(qū),然后調(diào)用將失敗灾而,并將被拋出TransactionTooLargeException胡控。
[解決方法] 不要將大量數(shù)據(jù)傳入Binder
1.14 java.lang.IncompatibleClassChangeError
[解決方案]
不兼容的類變化錯誤。當(dāng)正在執(zhí)行的方法所依賴的類定義發(fā)生了不兼容的改變時旁趟,拋出該異常昼激。一般在修改了應(yīng)用中的某些類的聲明定義而沒有對整個應(yīng)用重新編譯而直接運行的情況下,容易引發(fā)該錯誤
1.15 java.lang.OutOfMemoryError
[解決方案]
該異常表示未能成功分配字節(jié)內(nèi)存锡搜,通常是因為內(nèi)存不足導(dǎo)致的內(nèi)存溢出橙困。
[解決方案]:OOM就是內(nèi)存溢出,即Out of Memory耕餐。也就是說內(nèi)存占有量超過了VM所分配的最大凡傅。怎么解決OOM,通常OOM都發(fā)生在需要用到大量內(nèi)存的情況下(創(chuàng)建或解析Bitmap肠缔,分配特大的數(shù)組等)夏跷,這里列舉常見避免OOM的幾個注意點:
1.適當(dāng)調(diào)整圖像大小哼转。
2.采用合適的緩存策略。
3.采用低內(nèi)存占用量的編碼方式槽华,比如Bitmap.Config.ARGB_4444比Bitmap.Config.ARGB_8888更省內(nèi)存壹蔓。
4.及時回收Bitmap。
5.不要在循環(huán)中創(chuàng)建過多的本地變量猫态。
6.自定義對內(nèi)存分配大小佣蓉。
7.特殊情況可在mainfests的Application中增加 android:largeHeap="true"屬性,比如臨時創(chuàng)建多個小圖片(地圖marker)
1.16 android.os.DeadSystemException
1.17 java.lang.RuntimeException
Can't create handler inside thread that has not called Looper.prepare()
【解決方案】
該異常表示不能在非UI線程里面創(chuàng)建handler對象懂鸵,通常是因為在工作線程中處理UI相關(guān)的操作或者在非UI線程中new新的Handler導(dǎo)致偏螺;
不能在子線程里Toast等操作UI線程
[解決方案]:android中的UI操作都必須在主線程中處理的行疏,在涉及UI操作時通炒夜猓可以:
1.使用mHandler = new Handler(Looper.getMainLooper()),然后在handler中處理操作酿联;
2.使用 Activity.runOnUiThread()方法终息。
OOM是常見的java錯誤,OOM主要有:
1.OOM fo heapjava.lang:OutOfMemoryError: Java heap space贞让,此OOM是由于JVM中heap的最大值不滿足需要周崭,將設(shè)置heap的最大值調(diào)高即可。
2.OOM for Perm:java.lang:OutOfMemoryError: Java perm space喳张,此OOM是由于JVM中perm的最大值不滿足需要续镇,將設(shè)置perm的最大值調(diào)高即可,參數(shù)樣例為:-XX:MaxPermSize=512M
3.OOM for GC=>例如:java.lang:OutOfMemoryError: GC overhead limit exceeded销部,此OOM是由于JVM在GC時摸航,對象過多,導(dǎo)致內(nèi)存溢出舅桩,建議調(diào)整GC的策略
4.OOM for native thread created:java.lang.OutOfMemoryError: unable to create new native thread,此OOM是由于進程剩余的空間不足酱虎,導(dǎo)致創(chuàng)建進程失敗
5.OOM for allocate huge array:Exception in thread "main": java.lang.OutOfMemoryError: Requested array size exceeds VM limit,此類信息表明應(yīng)用程序(或者被應(yīng)用程序調(diào)用的APIs)試圖分配一個大于堆大小的數(shù)組
6.OOM for small swap:Exception in thread "main": java.lang.OutOfMemoryError: request <size> bytes for <reason>. Out of swap space?,拋出這類錯誤擂涛,是由于從native堆中分配內(nèi)存失敗读串,并且堆內(nèi)存可能接近耗盡
7.OutOfMemoryError thrown while trying to throw OutOfMemoryError; no stack trace available,拋出這類錯誤,一般是由于方法重復(fù)調(diào)用撒妈、死循環(huán)引起恢暖,直至內(nèi)存耗盡
[解決方案]The core Android system has died and is going through a runtime restart. All running apps will be promptly killed. 應(yīng)用調(diào)用相關(guān)接口時,此時會拋出RuntimeException狰右,而不會拋出DeadSystemException胀茵,此處可以應(yīng)用可以捕獲運行時異常RuntimeException。
2.ANR分析策略
1.Subject: Input dispatching timed out (Waiting because no window has focus but there is a focused application that may eventually add a window when it finishes starting up.)
【解決方案】1.查看/data/anr/traces.txt文件挟阻,搜索包名關(guān)鍵字琼娘,找到打印出的堆棧信息