前言
上一篇給大家介紹了Android Crash中的Java Crash分析狱掂,我們可以知道Java Crash一般會(huì)彈出提示框告訴我們程序崩潰了演痒,通常使用Crash工具都能夠捕獲到;本篇博客來談?wù)勅绾吾槍?duì)Native Crash進(jìn)行分析趋惨,它相對(duì)與Java層面的Crash有什么特點(diǎn)鸟顺?如何判斷程序Crash是因?yàn)镹ative層導(dǎo)致的?我們?cè)趺慈シ治鏊飨海肯旅嫖覀円粋€(gè)一個(gè)解答這些問題讯嫂。
Native Crash在Android上的特點(diǎn)
- 出錯(cuò)時(shí)界面不會(huì)彈出提示框提醒程序崩潰(Android 5.0以下)
- 出錯(cuò)時(shí)會(huì)彈出提示框提醒程序崩潰(Android 5.0以上)
- 程序會(huì)直接閃退到系統(tǒng)桌面
- 這類錯(cuò)誤一般是由C++層代碼錯(cuò)誤引起的
- 絕大部分Crash工具不能夠捕獲
我們?cè)趯?shí)際Android開發(fā)的時(shí)候,可能會(huì)引入第三方的一些so庫或者自己開發(fā)相應(yīng)的so庫供程序使用兆沙,然而so庫一般是通過c或者c++開發(fā)的欧芽。Android開發(fā)者通過java層的JNI機(jī)制調(diào)用Native語言寫的函數(shù),然而Natice語言也可以調(diào)用java層的函數(shù)葛圃。 如果有同學(xué)不明白的話千扔,建議先去了解下JNI的相應(yīng)技術(shù),總的來說通過JNI技術(shù)库正,就讓我們讓Java世界跟Native世界可以聯(lián)系在一起曲楚,也因?yàn)檫@個(gè)特性,讓Java具有跨平臺(tái)的特性褥符。
如果想了解如何通過Android Studio制作so庫龙誊,這篇文章可以幫到你:http://blog.csdn.net/wwj_748/article/details/51274580
Native Crash是如何產(chǎn)生的?
上一節(jié)我們談到so庫是同通過Native語言開發(fā)的喷楣,自然在Android中使用so庫的時(shí)候發(fā)生的Crash趟大,就是我們所說的Native Crash鹤树。為了更好的讓大家知道Native Crash是如何產(chǎn)生的,下面筆者舉一個(gè)例子:
Java層定義Native方法
本地方法跟普通的Java方法的區(qū)別在于方法聲明多了native關(guān)鍵字护昧。
JNI層實(shí)現(xiàn)Native方法
這里我們制造一個(gè)Native Crash魂迄,空指針異常。
通過Java調(diào)用Native方法
要調(diào)用Native方法需要先加載我們開發(fā)好的so庫惋耙,通過System.loadLibrary(“so名字”);來調(diào)用捣炬,然后在通過java調(diào)用聲明的native方法。
Native Crash如何分析绽榛?
既然要分析就必須找到可以分析的東西湿酸,我們?cè)诜治鯦ava層Crash的時(shí)候是通過logcat日志找到對(duì)應(yīng)的出錯(cuò)代碼,然而Native層Crash也是可以logcat日志來進(jìn)行分析的灭美。
這里我們截取上面制造的crash在logcat顯示的日志:
這個(gè)是什么鬼推溃,看不懂啊有木有。這個(gè)出錯(cuò)信息是我們調(diào)用native函數(shù)時(shí)打印出來的日志届腐,只是簡(jiǎn)單的描述出錯(cuò)信號(hào)铁坎,出錯(cuò)地址還有進(jìn)程號(hào),看這個(gè)是完全摸不著調(diào)的犁苏。不過系統(tǒng)還是會(huì)提供相關(guān)有用的日志硬萍,我們?cè)贏ndroid Studio查看logcat的時(shí)候需要做一下過濾。
在logcat添加完”DEBUG”的過濾項(xiàng)之后围详,我們就能得到以下log:
這下子可分析的內(nèi)容就多起來了朴乖,我們逐個(gè)來看看:
- 進(jìn)程信息:pid表示進(jìn)程號(hào),tid表示線程號(hào)助赞,name表示進(jìn)程名
- 錯(cuò)誤信號(hào):signal 11表示信號(hào)的數(shù)字买羞,SIGSEGV表示信號(hào)的名字,code 1(SEGV_MAPERR)表示出錯(cuò)代碼雹食,fault addr 00000000 表示出錯(cuò)的地址畜普。
- 寄存器快照:進(jìn)程收到錯(cuò)誤信號(hào)時(shí)保存下來的寄存器快照,一共有15個(gè)寄存器群叶。
- 堆棧信息:##00表示棧頂漠嵌,##01調(diào)用#00,以此往下都是嵌套的調(diào)用關(guān)系盖呼,直至到棧頂。
這里參考了:
http://bugly.qq.com/bbs/forum.php?mod=viewthread&tid=27&extra=page=4
我們?cè)跅m斁鸵呀?jīng)看到我們出錯(cuò)的地方了:
#00 pc 00000730 /data/app-lib/com.devilwwj.jnidemo-1/libJNIDemo.so (Java_com_devilwwj_jnidemo_TestJNI_createANativeCrash)
pc 00000730 表示出錯(cuò)的地址化撕,后面可以看到我加載了libJNIDemo.so庫几晤,接著是我們前面聲明的Native方法,通過這種方法我們就能準(zhǔn)確的找到出錯(cuò)的地方植阴。
從上面的分析我們可以看到蟹瘾,so庫崩潰時(shí)會(huì)產(chǎn)生信號(hào)異常圾浅,如果我們能夠捕獲到信號(hào)異常,相當(dāng)于我們也能夠顧捕獲到Android Native崩潰了憾朴。
總結(jié)
關(guān)于Native Crash的特點(diǎn)狸捕、產(chǎn)生原因、分析過程已經(jīng)給大家做了簡(jiǎn)單的分析众雷,這一塊內(nèi)容是初學(xué)者在分析錯(cuò)誤的時(shí)候最頭痛的地方灸拍,因?yàn)樗恢廊绾蜗率郑蚕Mㄟ^這篇文章能幫助到大家對(duì)Native Crash分析有個(gè)初步的認(rèn)識(shí)砾省,關(guān)于這一塊還有很多東西可以講鸡岗,比如具體的signal有哪些,Linux下的信號(hào)機(jī)制是怎樣的编兄,怎樣才能夠捕獲到信號(hào)等等轩性,關(guān)于Native層的Crash捕獲,我們有沒有第三方的開發(fā)工具能幫助到我們狠鸳,這里就要隆重推薦大家使用Bugly揣苏,可以說是業(yè)內(nèi)領(lǐng)先的崩潰捕獲工具,不僅能夠幫助我們獲取到完整的錯(cuò)誤堆棧件舵,還能夠?qū)⒊鲥e(cuò)的上下文環(huán)境參數(shù)(比如系統(tǒng)版本卸察、設(shè)備信息、內(nèi)存信息等)詳細(xì)的展現(xiàn)出來芦圾,大家不妨可以嘗試下蛾派。最后,感謝大家的閱讀个少。