欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android 是如何捕捉 java 異常的

 更新時(shí)間:2021年09月24日 09:57:08   作者:codelang  
這篇文章主要介紹Android 是如何捕捉 java 異常的,他是怎么實(shí)現(xiàn)全局捕捉的,帶著這樣的疑問(wèn)和小編一起閱讀下面文章的具體內(nèi)容吧

一、 java 異常全局捕捉

用于 java 異常全局捕捉代碼:

 val default = Thread.getDefaultUncaughtExceptionHandler()
​
Thread.setDefaultUncaughtExceptionHandler { t, e ->
    // 處理異常
    Log.e("Uncaught", "exception message : "+ e.message)
    // 將異常回執(zhí)給原注冊(cè)的 handler
    default.uncaughtException(t, e)
}


以上是很簡(jiǎn)單的一段代碼,經(jīng)常被用于 java 異常全局捕捉,但我的疑問(wèn)是,他是怎么實(shí)現(xiàn)全局捕捉的,帶著這樣的疑問(wèn),我們來(lái)扒一下代碼看看。

順藤摸瓜,我們看看靜態(tài)方法 getDefaultUncaughtExceptionHandler 是被誰(shuí)調(diào)用的,看了下所有的類(lèi)調(diào)用的類(lèi),唯有 ThreadGroup 最靠譜:

parent 為空的情況下,就會(huì)調(diào)用 getDefaultUncaughtExceptionHandler 來(lái)回調(diào)異常,然后繼續(xù)順藤摸瓜,看看 ThreadGroup uncaughtException 是被誰(shuí)觸發(fā)的,搜了一個(gè)圈,沒(méi)有一個(gè)靠譜的。在我躊躇時(shí),順帶瞄了一眼注釋?zhuān)?strong>奇跡發(fā)現(xiàn):

-   Called by the Java Virtual Machine when a thread in this
-   thread group stops because of an uncaught exception, and the thread
-   does not have a specific {[@link ](/link%20)Thread.UncaughtExceptionHandler}
-   installed.


意思是:當(dāng)一個(gè)未捕獲的異常導(dǎo)致線(xiàn)程組中的線(xiàn)程停止時(shí),JVM 會(huì)調(diào)用該方法。那我們就去搜搜 jvm 的源碼,看看是怎么觸發(fā)這個(gè)方法的。 ​

Hotspot 虛擬機(jī)源碼的 thread.cpp 中的 JavaThread::exit 方法發(fā)現(xiàn)了這樣的一段代碼,并且還給出了注釋?zhuān)?/p>

在線(xiàn)程調(diào)用 exit 退出時(shí),如果有未捕獲的異常,則會(huì)調(diào)用 Thread.dispatchUncaughtException 方法,然后我們繼續(xù)跟蹤該方法:

然后調(diào)用當(dāng)前線(xiàn)程的 uncaughtException 分發(fā)異常:

有意思的來(lái)了,如果我們沒(méi)有給當(dāng)前線(xiàn)程設(shè)置 UncaughtExceptionHandler ,則會(huì)將這個(gè)異常交給當(dāng)前線(xiàn)程的 ThreadGroup 處理。如果我們給當(dāng)前線(xiàn)程設(shè)置了 UncaughtExceptionHandler,則當(dāng)前線(xiàn)程發(fā)生了異常,永遠(yuǎn)也不會(huì)拋給 getDefaultUncaughtExceptionHandler,該功能適合捕捉當(dāng)前線(xiàn)程異常來(lái)用。 ​

終于回到了我們起初看到的 ThreadGroup.UncaughtExceptionHandler 方法,貼回原來(lái)的圖繼續(xù)分析:

這個(gè)地方會(huì)繼續(xù)判斷 parent 是否為空,parent 是個(gè) ThreadGroupThreadGroup 實(shí)現(xiàn)了 Thread.UncaughtExceptionHandler 接口。這里我就直接說(shuō)答案了,后面再說(shuō) ThreadGroup 和 Thread 的關(guān)系,最終會(huì)走到 system 的 ThreadGroup,system 的 parent 是個(gè)空,這時(shí)候走 else 分支,獲取 Thread 中的 getDefaultUncaughtExceptionHandler 靜態(tài)變量,觸發(fā) uncaughtException 方法,由于我們?cè)?Activity 中設(shè)置了這個(gè)靜態(tài)變量,所以,我們收到了這個(gè)異常通知。 ​

二、小知識(shí)

1、如何捕獲異常不退出

val default = Thread.getDefaultUncaughtExceptionHandler()
​
Log.e("Uncaught", "Uncaught handler: "+ default)
// Uncaught handler: com.android.internal.os.RuntimeInit$KillApplicationHandler@21f02a3
​
Thread.setDefaultUncaughtExceptionHandler { t, e ->
    // 將異常回執(zhí)給原注冊(cè)的 handler
    // default.uncaughtException(t, e)
}


捕獲異常后,什么都不處理。但這樣做顯得非常不地道,這樣會(huì)導(dǎo)致其他框架無(wú)法通過(guò)之前設(shè)置的靜態(tài)變量捕獲到異常上報(bào)。我打印了一下 default 是 RuntimeInit,該類(lèi)在捕獲到異常后,會(huì)做 killProcess。 ​

2、如何捕獲指定線(xiàn)程異常

val thread = Thread {
      val a = 1/0
}
thread.setUncaughtExceptionHandler { t, e ->
        Log.e("Uncaught", "Uncaught trace: "+ e.message)
}
thread.start() 



3、ThreadGroup 和 Thread 的關(guān)系結(jié)構(gòu)

  • Thread parent 是在 new Thread 的時(shí)候指定的,構(gòu)造可傳自定義的 ThreadGroup,默認(rèn)是使用創(chuàng)建當(dāng)前線(xiàn)程的 ThreadGroup
  • Thread 添加進(jìn) ThreadGroup Thread[] 數(shù)組時(shí)機(jī)是在調(diào)用 start 啟動(dòng)線(xiàn)程的時(shí)候做的
  • ThreadGroup 的 parent 是在 new ThreadGroup 的時(shí)候指定的,構(gòu)造可傳自定義的 ThreadGroup,默認(rèn)是使用當(dāng)前線(xiàn)程的 ThreadGroup

到此這篇關(guān)于A(yíng)ndroid 是如何捕捉 java 異常的的文章就介紹到這了,更多相關(guān)Android 捕捉 java 異常內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論