有Java層面,和Native層面。
成都創(chuàng)新互聯(lián)公司服務(wù)項目包括循化網(wǎng)站建設(shè)、循化網(wǎng)站制作、循化網(wǎng)頁制作以及循化網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,循化網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到循化省份的部分城市,未來相信會繼續(xù)擴大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!在我們平常操作中,如果有未捕獲的異常,會導(dǎo)致系統(tǒng)崩潰,這個崩潰本質(zhì)上是人為操作的,人為去操作系統(tǒng)主動退出(后面講源碼的地方可以看到)。
ANR系統(tǒng)因為線程阻塞問題,導(dǎo)致的無響應(yīng)。
WTF(What a Terrible Failure)一般指,系統(tǒng)中自己編碼沒有按照android要求進行,例如發(fā)送未受保護的廣播、啟動的Activity未在注冊文件里注冊等等;
這個一般不用太關(guān)注,主要寫代碼按標(biāo)準(zhǔn)來就行。
首先我們先明確一個目的,我們的main函數(shù)的啟用本身作為主線程存在,那么在我們想要探索系統(tǒng)到底如何處理異常,需要去關(guān)注到一個類Thread;
在我們的程序代碼中,如果存在一個異常,任何地方都沒有去捕獲處理它的話,它就會一路往上拋,最終來到main函數(shù),如果main函數(shù)也沒有處理這個異常,就會給到JVM來處理,JVM會給到當(dāng)前的線程Thread來處理。
源碼分析步驟2在Thread類中,看到一段這樣的函數(shù)dispatchUncaughtException();
注釋翻譯為:向處理程序發(fā)送未捕獲的異常。此方法旨在僅由JVM調(diào)用;可以理解為,未處理的異常會走到這里來:
在上圖我們可以看到官方明確告知,JVM在處理未經(jīng)捕獲的異常時,會調(diào)用當(dāng)前dispatchUncaughtException函數(shù)進行處理,這個里面我們能看到一個類型為UncaughtExceptionHandler的類。
在上圖的邏輯中我們可以看到如果沒有設(shè)置uncaughtExceptionHandler,將使用線程所在的線程組(ThreadGroup)來處理這個未捕獲異常。線程組ThreadGroup實現(xiàn)了UncaughtExceptionHandler,所以可以用來處理未捕獲異常。
源碼分析步驟3所以,我們重點來看ThreadGroup中,是如何來處理未捕獲異常的:在Thread類的dispatchUncaughtException函數(shù)中,最后調(diào)用了getUncaughtExceptionHandler().uncaughtException(this, e); 我們知道這個getUncaughtExceptionHandler()返回的是ThreadGroup,所以我們來看ThreadGroup中的uncaughtException方法:
默認情況下,ThreadGroup處理未捕獲異常的邏輯是:
首先將異常消息通知給父線程組(如果parent不為空的話);
然后嘗試?yán)靡粋€默認的defaultUncaughtExceptionHandler來處理異常;
如果沒有默認的異常處理器則將錯誤信息輸出打印到System.err。
這里可以思考下,我們可以自定義一個異常處理類,繼承下 Thread.UncaughtExceptionHandler,然后去處理未捕獲的異常。記得需要手動去調(diào)用Thread.setUncaughtExceptionPreHandler()方法設(shè)置下,有了這個自定義異常處理類,就可以做相應(yīng)的崩潰優(yōu)化。
源碼分析步驟4回到Thread中,思考下:既然他是通過getDefaultUncaughtExceptionHandler來處理,現(xiàn)在我們并沒有看到有相關(guān)的設(shè)置,但是在Thread中我們看到了他對外提供了對應(yīng)的設(shè)置函數(shù):Thread.setUncaughtExceptionPreHandler()。
源碼分析步驟5思考下:系統(tǒng)是否會有地方默認給我們設(shè)置了uncaughtExceptionHandler?
因為從上面的源碼看來,我們并沒有看到有讓系統(tǒng)直接崩潰掉的情況,因為默認是ThreadGroup去處理,他只不過是做了一個日志信息的記錄,不會有退出的情況,那么肯定是有哪個地方默認設(shè)置了uncaughtExceptionHandler,讓系統(tǒng)退出的。
源碼分析步驟6來看下RuntimeInit這個類,zygote負責(zé)啟動RuntimeInit進程(作用:app運行時環(huán)境初始化,用來初始化運行時的一系列信息,其中包含異常處理),它里面有個main方法:
這里設(shè)置了默認的異常處理:KillApplicationHandler。
源碼分析步驟7我們來看下KillApplicationHandler:
重點來看 uncaughtException(Thread t, Throwable e)這個方法:
看到這里就知道了,默認的異常處理(殺進程)是在RuntimeInit進程(作用:app運行時環(huán)境初始化,用來初始化運行時的一系列信息,其中包含異常處理)的main()方法里設(shè)置的。
小總結(jié)在上面的源碼分析步驟7我們知道了,在KillApplicationHandler的uncaughtException()方法里,最終異常信息有一個AMS上報過程:
來看下ActivityManagerService.handleApplicationCrash()方法:
從上面可以看出,若傳入app為null時,processName就設(shè)置為system_server,意思是:如果沒有來源默認判定是系統(tǒng)進程自己。接著看handleApplicationCrashInner(String eventType......)方法:
參數(shù)eventType是指事件類型,具體如下:
Java層未捕捉的異常:crash
ANR:anr
native層的異常:native_crash
現(xiàn)在我們看的是java的異常,所以這個類型傳的是crash。
接著看handleApplicationCrashInner()函數(shù):
中間的可以先不管他們,這個可以理解為在進行系統(tǒng)日志輸出,具體的處理是在addErrorToDropBox()函數(shù)中。
重點注意:無論是java crash、native_crash、ANR或是wtf,最終都是來到這里,交由addErrorToDropBox()函數(shù)去處理。
addErrorToDropBox()函數(shù)和DropBoxManager有關(guān),Android Dropbox 是 Android 在 Froyo(API level 8) 引入的用來持續(xù)化存儲系統(tǒng)數(shù)據(jù)的機制。主要用于記錄 Android 運行過程中, 內(nèi)核, 系統(tǒng)進程, 用戶進程等出現(xiàn)嚴(yán)重問題時的 log, 可以認為這是一個可持續(xù)存儲的系統(tǒng)級別的 logcat。
記錄位置:在data/system/dropbox中:
也就是說,我們想要看系統(tǒng)的崩潰日志,可以在這個文件路徑下找。
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧
當(dāng)前題目:崩潰優(yōu)化之Java層crash原理分析-創(chuàng)新互聯(lián)
標(biāo)題URL:http://jinyejixie.com/article48/cescep.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制開發(fā)、網(wǎng)頁設(shè)計公司、網(wǎng)站制作、軟件開發(fā)、云服務(wù)器、網(wǎng)站策劃
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)