Android程序員不得不知的調試技巧。 本文以webview loadUrl和域名解析為例,介紹配合使用LLDB和Android Studio調試Framework代碼的技巧。
java 層調試
首先需要把AOSP源碼導入到Android Studio中,如果是macOS系統可以參考這篇文章。 導入后如下圖所示:
調試原理
Java平臺的調試是有一個規范化的標準的,那就是JPDA(Java Platform Debugger Architecture);通過 JPDA 提供的 API,開發人員可以方便靈活的搭建 Java 調試應用程序。 JPDA 主要由三個部分組成:Java 虛擬機工具接口(JVMTI),Java 調試線協議(JDWP),以及 Java 調試接口(JDI)。 調試需要堆棧、符號等信息都保存在JVM中,調試器(debugger)需要通過一種渠道獲取這些信息,并通過這個渠道發送調試指令給JVM,JDWP就是調試器與JVM通信的渠道。在JVM內部有一個專門的jdwp線程,Android系統的adbd守護進程通過socket與各個虛擬機的jdwp線程進行通信,外部調試器通過主機的adb與adbd通信進而完成與jdwp的通信。具體過程如下圖:
配置Debug選項
在菜單欄上依次點擊Run -> Edit Configurations -> Remote,打開并配置成如下的頁面
Exclued 不必要的文件夾
在斷點調試時,JVM會告訴AS自己在xx.java的第xx行被斷住了,AS就會定位到這個位置,但是如果有重復的文件的名的,往往會出現定位不準的情況,所以需要把不必要的文件夾排除在整個源碼結構之外。打開Project Structure,做如下修改 如果遇上斷點文件對不上的情況時,就手動在這里Exclued好了。 也可以直接修改aosp-root/development/tools/idegen/excluded-paths文件中的內容,添加exclude,再運行idegen.sh?重新生成IDE代碼樹。
在源碼處打斷點
我們在WebView.java的loadUrl處打斷點 點擊調試按鈕,你會看到Console中的提示
1 Connected to the target VM, address: 'localhost:8700' , transport: 'socket'
打開DDMS
在菜單欄上依次點擊Tools ->Android -> Android Device Monitor,打開DDMS后,點擊
在monitor中我們可以看到有3列,分別是
進程名(以包名顯示) PID(Process ID) 端口號(映射端口號/實際端口號) 點擊我們要調試的browser程序的那一行,會出現一只綠色的bug,表示我們的Debugger已經跟設備上的程序聯系上,可以調試了。
開始調試
當在瀏覽器中加載一個網頁時,就能觸發之前設置的loadUrl的斷點了,如此就可以使用各種調試手段了。
C++層調試
Android Framework中native代碼的調試方法采用的是 2.2以上版本的Android Studio配合LLDB調試器。 這里以調試webview的dns查找過程為例,說明native調試的方法。
調試原理
LLDB作為Android Native層的調試工具,其原理跟gdb一樣,也是采用C/S架構,通過push一個lldb-server到設備上,pc機的debugger作為lldb-client與其通信,以達到調試的效果。 C++在編譯時有一個選項-g表示編譯出來的可執行文件是帶有調試信息的,比如源文件、行號信息,都會存放在ELF文件中的 .debug_*段之中, 知道了這些調試信息后,調試器配合IDE就可以定位代碼了。 這里還需要保證你的符號文件和設備上真正運行的動態鏈接庫或者可執行文件是對應的,就是同一份,不然調試信息就對不上了。 最簡單的辦法就是使用模擬器。我們編譯完源碼之后,一個主要的編譯產物就是 system.img,這個 system.img會在啟動之后掛載到設備的 /system 分區,而system分區包含了Android系統運行時的絕大部分可執行文件和動態鏈接庫,而這些文件就是我們的編譯輸出,正好可以與編譯得到的調試符號進行配合調試。模擬器有一個 -system選項用來指定模擬器使用的 system.img文件。
1 $ emulator -avd Nexus5-API22 -verbose -no -boot-anim -system (the path of system.img)
我這里的做法是使用燒錄了自己編譯源碼的Nexus手機。
配置Debugger
這里需要新建一個Android Demo工程了,直接用AOSP源碼那個工程,沒有是Native Debug那個選項的。 按如下方式配置符號表,需要與設備上用的so是同一份。并且改Debug type 為Native。 符號表的添加也可以通過lldb命令行的方式添加 LLDB需要這些符號信息才能幫你定位到調試斷點的代碼。
配置源碼到AS
當LLDB告訴AS源文件行號信息時,AS需要定位到對應的代碼處,所以必須先把源文件導入到AS中,最簡單的做法是建立軟鏈接。在Android Demo工程下建立一個source文件夾,然后執行如下命令。
12 $ ln -s xx/external/chromium_org xx/source /chromium_org$ ln -s xx/bionic/libc xx/source /libc
這里只是把需要用到的源文件導入進來,當然也可以把整個AOSP源碼導入AS中,但是這樣會比較耗時。
打斷點
我在getaddrinfo.c的getaddrinfo方法處打一個斷點,看看webview在加載網頁時的域名解析會不會走到這里。 點擊Debug按鈕,當Demo程序開始LoadUrl之后,就會被Debug斷住,如下是chromium域名解析線程的堆棧(這里的方法名真夠長的。。。),這樣我們就可以進一步了解webview加載網頁時域名解析的過程了。 讓我們看看其他線程在干啥,整個世界都停止了。
不足之處
目前的調試framework方案只能把java層和c++ native層的分開來做,還不能做到java層和c++ native層互相跳轉的效果。雖然目前我們開發Android App用AS調試時能做大這一點,要是framework的調試也能做到這一點就好了。獲取真有這樣的方法,如果有知道的大神,還請賜教。
相關鏈接
Debugging AOSP Platform code with Android Studio - Part I - Java Debugger Android Debugging: Old School bringup routines - Command line Java debugging with JDWP 如何調試Android Framework 如何調試Android Native Framework
在macOS 10.12 上編譯 Android 5.1
轉載: http://felixzhang00.github.io/2017/01/23/%E7%94%A8Android%20Studio%E8%B0%83%E8%AF%95Framework%E5%B1%82%E4%BB%A3%E7%A0%81/
總結
以上是生活随笔 為你收集整理的用Android Studio调试Framework层代码 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。