直接使用JDB解決ndk-gdb調試時的「waiting for debugger」彈窗不消失問題

一 概述
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窗口。

相關文章
相關標籤/搜索