成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

如何調(diào)試Android Framework?

移動(dòng)開發(fā) Android
如果你仔細(xì)看完了本文和我給出的鏈接,那么應(yīng)該對Debug技術(shù)不再陌生了;接下來你可以選擇Framework層的代碼,手動(dòng)調(diào)試一下加深理解;在日后的工作過程中,不斷滴加強(qiáng)debug技術(shù)的練習(xí),讓它稱為你解決復(fù)雜問題的條件反射,一定會(huì)事半功倍!

Linus有一句名言廣為人知:Read the fucking source code. 但其實(shí),要深入理解某個(gè)軟件、框架或者系統(tǒng)的工作原理,僅僅「看」代碼是遠(yuǎn)遠(yuǎn)不夠的。就拿Android Framework來說,整個(gè)代碼量非常大不說,那些個(gè)動(dòng)輒幾萬行的類如何去理解?所以我今天要說的就是:

Debug the fucking source code!!

之前分享過一個(gè)答案:大家遇到過什么 Android 兼容性問題?,這里面的有一些非常詭異的問題,我相信光靠看代碼你是永遠(yuǎn)定位不出來的。還有我寫的一系列Android插件框架原理的文章,這里面涉及到大量Android Framework層的知識(shí),有小伙伴會(huì)問,這些Framework層的原理,你是如何學(xué)習(xí)的呢,有訣竅嗎?有!那就是調(diào)試。

Debug是一項(xiàng)非常非常重要的技能,毋庸多言。今天我就給大家分享一下「調(diào)試Android Framework」的經(jīng)驗(yàn),一旦掌握這項(xiàng)技能,那么Java層的任何問題都攔不住你了。

概覽

其實(shí)整個(gè)調(diào)試過程非常簡單:

  • 在你要調(diào)試進(jìn)程的合適位置打上斷點(diǎn)
  • 跟蹤代碼(Step in/out/over等等)

在展開講述這兩方面之前,有必要先簡單了解下調(diào)試的基礎(chǔ)知識(shí)。Java平臺(tái)的調(diào)試是有一個(gè)規(guī)范化的標(biāo)準(zhǔn)的,那就是JPDA(Java Platform Debugger Architecture);通過 JPDA 提供的 API,開發(fā)人員可以方便靈活的搭建 Java 調(diào)試應(yīng)用程序。 JPDA 主要由三個(gè)部分組成:Java 虛擬機(jī)工具接口(JVMTI),Java 調(diào)試線協(xié)議(JDWP),以及 Java 調(diào)試接口(JDI)。

Java程序的調(diào)試無非就是通過一個(gè)調(diào)試器(debugger)獲取對應(yīng)Java虛擬機(jī)的信息,上文所述的JDWP就是調(diào)試器與虛擬機(jī)通信的橋梁。在dalvik虛擬機(jī)內(nèi)部有一個(gè)專門的jdwp線程,Android系統(tǒng)的adbd進(jìn)程通過socket與各個(gè)虛擬機(jī)的jdwp線程進(jìn)行通信,外部調(diào)試器通過adb工具與adbd通信進(jìn)而完成與jdwp的通信。我們通常所說的「attach debugger」指的就是這個(gè)意思——連接到指定的需要調(diào)試的進(jìn)程。 

 

 

調(diào)試器工作原理 

調(diào)試器工作原理

如何在正確的地方下斷點(diǎn)

「正確的地方」包含兩個(gè)含義:首先,調(diào)試是以進(jìn)程為單位進(jìn)行的,如果你需要調(diào)試運(yùn)行在進(jìn)程A 中的代碼,卻把debugger attach到了B進(jìn)程,那么這個(gè)斷點(diǎn)壓根兒就是牛頭不對馬嘴;另外呢,比如你想調(diào)試Android的多媒體框架,你得知道m(xù)edia相關(guān)的類在哪吧,也就是說需要在正確的函數(shù)里面下斷點(diǎn)。

如何在合適的進(jìn)程下斷點(diǎn)?

如果是調(diào)試我們自己寫的App,在Android Studio里面非常簡單,在Run菜單de最后面有一個(gè)attach debugger to android process 的選項(xiàng),點(diǎn)擊之后會(huì)出現(xiàn)一個(gè)菜單,選擇自己需要調(diào)試的進(jìn)程即可;但是,如果需要調(diào)試Android Framework層的代碼,這樣做是達(dá)不到目的的——Framework層的代碼通常運(yùn)行在別的進(jìn)程(比如ActivityManagerService運(yùn)行在system_server進(jìn)程),而這些進(jìn)程通常情況下是不可調(diào)試的,也就是說在attach debugger to android process 的那個(gè)菜單里面不會(huì)有系統(tǒng)的進(jìn)程,如下圖: 

 

 

普通的無法調(diào)試的Android設(shè)備 

普通的無法調(diào)試的Android設(shè)備

為什么不可調(diào)試呢?上文我們簡要講述了調(diào)試器的工作原理,我們知道每一個(gè)虛擬機(jī)有一個(gè)jdwp線程,如果這個(gè)線程拒絕連接到調(diào)試器,你也就沒辦法對這個(gè)進(jìn)程進(jìn)行調(diào)試了。Android的所有App進(jìn)程都是通過Zygote進(jìn)程fork出來的,我們在android.os.Process這個(gè)類里面可以看到android進(jìn)程的啟動(dòng)過程有這么一句:

  1. if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) { 
  2.  
  3.     argsForZygote.add("--enable-debugger"); 
  4.  
  5.  

也就是說,一個(gè)進(jìn)程是否可以調(diào)試是由進(jìn)程啟動(dòng)時(shí)候的參數(shù)決定的;普通的App進(jìn)程如果是debug keystore默認(rèn)是可以調(diào)試的,有或者你在AndroidManifest里面指定debuggable為true也是可以調(diào)試的。對系統(tǒng)進(jìn)程,我們只有采取系統(tǒng)級別的手段:讓整個(gè)系統(tǒng)可以調(diào)試——debug版或者編譯參數(shù)debuggable為1的系統(tǒng)。

解決這個(gè)辦法很簡單:使用模擬器(真機(jī)也行,限Nexus系列刷原生Android系統(tǒng),把系統(tǒng)啟動(dòng)的debuggable參數(shù)修改為1),我的Nexus 5 可以調(diào)試的進(jìn)程如下: 

 

 

可調(diào)試任意進(jìn)程的設(shè)備 

可調(diào)試任意進(jìn)程的設(shè)備

這樣,系統(tǒng)中所有的Android進(jìn)程都可以調(diào)試了;這一點(diǎn)很重要,比如你要分析Activity的啟動(dòng)流程,相當(dāng)多一部分代碼是在ActivityManagerService所在的進(jìn)程system_server執(zhí)行的,如果你把斷點(diǎn)打在別的進(jìn)程,就會(huì)產(chǎn)生跟丟了的情況。在比如,你要調(diào)試ActivityThread的main函數(shù),在main函數(shù)里面執(zhí)行了一句attach,最終調(diào)用AMS的attachApplication的時(shí)候,代碼就通過Binder IPC調(diào)用到了AMS的system_server進(jìn)程。

明白你要執(zhí)行的代碼運(yùn)行在哪一個(gè)進(jìn)程相當(dāng)重要,在Android中,由于Binder通信機(jī)制的存在,「進(jìn)程遷移」使用的非常非常頻繁,因此需要對binder機(jī)制有一定的了解;詳細(xì)的話可以參考我的博客:Binder學(xué)習(xí)指南

如何在對應(yīng)的代碼處下斷點(diǎn)?

假設(shè)我們現(xiàn)在把debugger attach到了正確的進(jìn)程,那么斷點(diǎn)應(yīng)該下在哪里呢?直觀來講,就是說我需要導(dǎo)入所有的Android源碼嗎?如果不是應(yīng)該導(dǎo)入哪些代碼,怎么導(dǎo)入?

首先,如果你需要調(diào)試的類在sdk里面導(dǎo)出了,你壓根兒就不需要再導(dǎo)入源碼,Android Studio自動(dòng)幫你關(guān)聯(lián)了這部分代碼(前提是你用SDK Manager下載了sdk的源碼,如下圖: 

 

 

SDK manager下載源碼 

SDK manager下載源碼

比如你要調(diào)試ActivityManagerServce類的attachApplication方法,那么很簡單;創(chuàng)建一個(gè)空的Android項(xiàng)目,SDK版本選擇與你要調(diào)試的模擬器/真機(jī) 的android相同(這很重要,下文會(huì)講述);然后attrach 到system_server進(jìn)程,直接在attach_application上面打上斷點(diǎn);隨便啟動(dòng)一個(gè)app,可以看到我們熟悉的調(diào)試界面: 

 

 

調(diào)試attachApplication 

調(diào)試attachApplication

如果這部分類在sdk中沒有導(dǎo)入(比如@hide)的,又或者壓根兒不是SDK的類,(比如系統(tǒng)app的源碼)那應(yīng)該怎么辦呢?直接導(dǎo)入這部分代碼即可。不需要是Android項(xiàng)目,普通的Java項(xiàng)目即可;舉個(gè)例子,假設(shè)你想調(diào)試原生Android系統(tǒng)的「系統(tǒng)設(shè)置」這個(gè)程序,該如何做呢?

根據(jù)上面的分析,我們首先得知道「系統(tǒng)設(shè)置˜」運(yùn)行在哪一個(gè)進(jìn)程,通常情況下進(jìn)程名字就是包名;我們查出設(shè)置的包名即可,而包名是在源碼的AndroidManifeist中聲明的,因此,我們找到「系統(tǒng)設(shè)置」這個(gè)程序的源碼即可;源碼在 https://android.googlesource.com/ ,系統(tǒng)App的源碼在/packages這個(gè)子目錄下面,我們一個(gè)個(gè)找,最終可以確定「系統(tǒng)設(shè)置」的源碼在https://android.googlesource.com/platform/packages/apps/Settings/ ;然后我們把這部分代碼git clone下來,導(dǎo)入Android Studio: 

 

 

調(diào)試Settings 

調(diào)試Settings

我們?nèi)ndroidManifest中查到,「系統(tǒng)設(shè)置」的包名為:com.android.settings,這樣我們attach到這個(gè)進(jìn)程 : 

 

 

attach setting進(jìn)程 

attach setting進(jìn)程

然后,我們隨便打個(gè)斷點(diǎn)玩一玩,比如進(jìn)入設(shè)置主界面的時(shí)候,斷下來;我們在AndroidManifest中查到設(shè)置程序的入口界面為:Settings,我們在這個(gè)類的onCreate里面打一個(gè)斷點(diǎn),然后進(jìn)入設(shè)置程序,發(fā)現(xiàn)完美滴斷下來了: 

 

 

在setting中斷點(diǎn)成功 

在setting中斷點(diǎn)成功

OK,到這里;應(yīng)該學(xué)會(huì)如何在正確的位置打斷點(diǎn)了:正確的進(jìn)程,正確的位置。接下來,要完成調(diào)試,還需要一些技巧。

如何跟蹤代碼?

或許你會(huì)說,跟蹤代碼不就是step in/out/over么,這有什么難的?但其實(shí)事情并沒有你想象的那么簡單,要優(yōu)雅滴調(diào)試,還是需要一些姿勢的。

行號(hào)對應(yīng)

跟蹤代碼一個(gè)首要的問題是行號(hào)對應(yīng)。如果你在正確位置下了斷點(diǎn),但是跟蹤的時(shí)候,單步調(diào)試,發(fā)現(xiàn)運(yùn)行的代碼和Android Studio里面的代碼對不上號(hào),那么就很蛋疼;要使得調(diào)試器的行號(hào)能夠?qū)?yīng),必須保證設(shè)備上的代碼和調(diào)試器的代碼是同一份;簡單來說,需要使用Android的原生系統(tǒng)(模擬器,Nexus系列真機(jī)),然后調(diào)試器里面使用的SDK版本,必須和設(shè)備的系統(tǒng)版本一致。

行號(hào)不對應(yīng)怎么辦?

一定要注意行號(hào)對應(yīng)這一點(diǎn),這會(huì)使調(diào)試過程簡單很多;如果沒有辦法,行號(hào)對不上,那該如何調(diào)試呢?

行號(hào)不對應(yīng)帶來的一個(gè)首要問題就是,下斷點(diǎn)的時(shí)候都有可能出現(xiàn)問題;比如你在TestClass的第100行下了一個(gè)斷點(diǎn),但是由于行號(hào)不對應(yīng),有可能真正執(zhí)行的代碼第100行是沒有意義的空行或者是在下一個(gè)函數(shù)里面,這樣斷點(diǎn)就沒有起到應(yīng)有的作用了。

要解決行好對應(yīng)的問題,必須使用方法斷點(diǎn);我們直接在某個(gè)函數(shù)的入口設(shè)置斷點(diǎn),這樣即使行號(hào)對不上,也能在正確的入口出斷下來,這一點(diǎn)非常重要。

解決了如何下斷點(diǎn)的問題,那么行號(hào)不對應(yīng),怎么知道執(zhí)行到哪了,怎么查看局部變量?

觀察棧楨

在Android Studio的調(diào)試器的左邊,顯示了每一個(gè)線程執(zhí)行的棧楨,棧楨里面包含了當(dāng)前線程豐富的信息: 

 

 

觀察棧楨 

看到?jīng)],真正運(yùn)行的代碼在哪一行,當(dāng)前運(yùn)行的是什么函數(shù)一目了然;接下來你在step into/out的時(shí)候,不能以源代碼的行數(shù)為準(zhǔn),而應(yīng)該以這個(gè)棧楨所顯示的代碼行數(shù)為準(zhǔn)。

熟練使用斷點(diǎn)

OK,現(xiàn)在不論行號(hào)是否能對應(yīng),我們都能正確滴下斷點(diǎn)調(diào)試了。斷點(diǎn)有很多種類型,方法斷點(diǎn),watch point,條件斷點(diǎn)都能夠很好滴輔助我們調(diào)試;如果你連這幾個(gè)名詞都沒有聽說過,一定要惡補(bǔ)一下;可以參閱我的博客:Android Studio你不知道的調(diào)試技巧;我就不再復(fù)述了。

如果你仔細(xì)看完了本文和我給出的鏈接,那么應(yīng)該對Debug技術(shù)不再陌生了;接下來你可以選擇Framework層的代碼,手動(dòng)調(diào)試一下加深理解;在日后的工作過程中,不斷滴加強(qiáng)debug技術(shù)的練習(xí),讓它稱為你解決復(fù)雜問題的條件反射,一定會(huì)事半功倍!還有記住:

Debug the fucking source code.

責(zé)任編輯:龐桂玉 來源: 安卓開發(fā)精選
相關(guān)推薦

2010-01-06 18:59:41

.Net Framew

2012-02-20 14:41:30

JavaPlay Framew

2021-02-04 18:04:53

DbContext開源對象

2010-03-01 11:06:52

Python 調(diào)試器

2013-05-28 10:52:07

Android開發(fā)移動(dòng)開發(fā)移動(dòng)應(yīng)用

2011-07-26 14:44:53

調(diào)試 Xcode

2011-09-13 17:44:00

Eclipse And

2023-07-14 08:29:55

AOT.Net程序

2021-03-30 11:33:45

云計(jì)算微服務(wù)云應(yīng)用

2023-07-10 12:11:50

TypeScripChrome識(shí)別

2021-06-21 09:00:00

Python代碼開發(fā)

2013-07-11 10:16:07

Android調(diào)試

2016-11-23 08:10:16

Android St JRebel調(diào)試神器

2019-11-13 15:40:00

Entity Fram審計(jì)數(shù)據(jù)數(shù)據(jù)庫

2010-01-06 15:56:18

.Net Framew

2021-08-07 07:23:08

Webpack中間件模型

2009-10-22 13:02:47

SQL CLR存儲(chǔ)過程

2010-08-13 11:06:24

2009-09-18 14:09:57

SQL CLR存儲(chǔ)過程

2010-07-30 14:30:36

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 精品久久久久久久久久久 | 欧美精品福利 | 日韩精品在线免费观看视频 | 高清欧美性猛交xxxx黑人猛交 | 成人国产精品久久 | 97精品久久| 日本 欧美 国产 | 欧美 日韩 中文 | 亚洲人在线播放 | 99精品国产一区二区三区 | 可以在线看的黄色网址 | 国产日韩精品一区二区三区 | 精品一区国产 | 色综合久久久 | 久久四虎 | 男女啪啪高潮无遮挡免费动态 | 久久福利电影 | 亚洲国产网址 | 国产精品久久国产精品久久 | h片在线免费看 | 亚洲综合视频 | 91久久久久久久久久久久久 | av黄色在线 | 欧美一区视频 | 欧美精品久久久 | 天堂一区在线 | 久久se精品一区精品二区 | 亚洲精品9999 | 有码一区 | 国产精品久久久久久亚洲调教 | 精品欧美一区二区精品久久久 | 国产免费又色又爽又黄在线观看 | a在线观看| www.99精品 | 国产91成人| 成人激情视频在线观看 | 日韩中出| 欧美一级二级视频 | 一区二区中文 | 久久99蜜桃综合影院免费观看 | 精品少妇一区二区三区在线播放 |