一 概述
java
如題的狀況,我是在蘋果(Mac)的筆記本電腦上調試時遇到的。我查了一下,已經有網友遇到過相似的狀況,其解決方法多數是,殺進程\重啓\啓動兩個eclipse調試.殺進程\重啓的方法我試過,對個人狀況不起做用,啓動兩個eclipse調試的方法我沒有試,由於安裝eclipse時出了些問題沒有安裝成功。如今回想起來以爲本文所說的方法,應該是能夠配合eclipse或Android Studio解決問題的。由於這兩個IDE其Java調試的底層也是用JDB實現的。android
二 問題描述shell
*(Mac)OS X Yosemite 版本 10.10.2bash
* Android SDK + android-ndk-r9c + ant + emacs (eclipse沒安裝成功,因此沒有用)
app
用NDK(android-ndk-r9c)的ndk-gdb —start 調用試(sample的)hellojni。但一啓動後就一直卡在以下這個畫面。我按模擬器的返「回鍵」,也關不了這個「waiting for debugger」彈出窗口。gdb已是成功啓動的,可是程序就是run不起來。eclipse
三 解決方法
tcp
由於直接使用JDB調試有一個問題,那就是程序要已經啓動了,JDB才能夠鏈接。這個就會「錯過」了程序啓動的的代碼。我在網上查到了一種直接用代碼停住程序的方法:加入「android.os.Debug.waitForDebugger();」測試
public class HelloJni extends Activity { ...... public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //就是下面這一句代碼可讓程序停下來等待JDB的鏈接 android.os.Debug.waitForDebugger(); TextView tv = new TextView(this); tv.setText( stringFromJNI() ); setContentView(tv); } ...... }
修改好代碼後,在Shell中進入Hellojni的工程根目錄,執行以下命令:ui
ndk-build NDK_DEBUG=1 android update project --target 5 --path . ant debug ant debug install
這樣就安裝好要調試的程序了,接下來是啓動調試了。這裏不要用「ndk-gdb —start」,而是用下面的腳本啓動gdb調試:(留意腳本中的註釋)this
#!/bin/bash adb kill-server sleep 1 adb start-server adb wait-for-device #(必填)這裏加入包名(俱體能夠參看AndroidManifest.xml中<manifest>中package屬性的設置) strPackage="com.example.hellojni" #(必填)這裏加入首先調用類名(一樣能夠參看AndroidManifest.xml,注意<activity>標籤的設置) strCls=".HelloJni" #(選填)若是你想調用的類(一般是Activity或Services等)就在package的頂層目錄的話。這裏只 #須要簡單地填入類名便可。但若是目標類不在頂層目錄,那麼這裏的類名要給出相對的包路 #徑或完整的包路徑。這個變量你能夠不做修改,原來的設置能夠根據前面的設置合成一個適當的值 strClsFullName="$strPackage""$strCls" #(必填)只鏈接USB設備,除必你硬性鏈接真機,要否則這裏通常都是false strIsOnlyUSB="false" #(必填)jdwp調試pid,映射到PC的一個端口(該端口值,相對隨意,只要是未被佔用,並且在合法範圍內便可) strPort="29882" #(必填)android工程的Java代碼所在目錄。 strSrcPath="./src" ################################### #把要測試的應用run起來 ################################### strDebugFlags="" if [ "$strIsOnlyUSB" == "true" ]; then strDebugFlags="-d" fi strDebugFlags="${strDebugFlags} shell am start -e debug true" #參看AndroidManifest.xml的<intent-filter> strIntentFilter="-a android.intent.action.MAIN -c android.intent.category.LAUNCHER" strCmd="adb ${strDebugFlags} ${strIntentFilter} -n ${strPackage}/${strClsFullName}" echo $strCmd exec $strCmd & sleep 2 ################################### #應用的pid綁定到pc的調試端口 ################################### #列出相關的進程ID爲主機進程的一個JAVA調試的無線協議的傳輸 #一般adb jdwp會列出一個列表,這裏只用到上面腳本剛啓動的ID,因此用到了"tail -1"意爲取倒數第一個 app_debug_pid=$(adb jdwp | tail -1); echo "app_debug_pid: $app_debug_pid"; strDebugFlags="" if [ "$strIsOnlyUSB" == "true" ]; then strDebugFlags="-d" fi strCmd="adb ${strDebugFlags} forward tcp:$strPort jdwp:$app_debug_pid"; echo $strCmd; exec $strCmd & ################################### #最關鍵的一步。用jdb鏈接指定的的端口進行調試 ################################### strCmd="sleep 3;jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=$strPort -sourcepath ${strSrcPath}" echo $strCmd; bash -c "$strCmd" & ndk-gdb
腳本成功運行後,會進入gdb的命令行。這時輸入「c 及回車」,就會進入jdb的命令行。用"ctrl + c"便可回到gdb的命令行。在此就可使用gdb正常調試了。是否是以爲操做有點怪怪的?其緣由簡單來講,是由於我在MAC平臺下沒有找到在腳本啓動新bash窗口。