如何使用jdb调试android的java程序

习惯了gdb,总觉得eclipse太过臃肿,各种不爽。看到李先静写了一篇“用jdb/jdbshell调试android程序“(http://www.limodev.cn/blog/archives/1281),用了下,感觉比eclipse舒服多了。jdb的命令有那么点别扭,先静写了个jdbshell,加入了命令历史和命令别名(几个常用的gdb命令)。

下面是一个简单的how to,以调试browser应用为例

1)下载jdbshell并编译

www.limodev.cn/blog/?dl_name=jdbshell.tar.gz

因为我基本上每次一开始都要执行threads变量,所以我在开始wile循环前加了一句话

else
{
close(parent_to_child[0]);
write(parent_to_child[1], "threads\n",strlen("threads\n"));
while(1)
{
int i = 0;
line = readline ("");

...

}

}

编译后将jdbshell放到~/bin,或者将目录加到PATH里

出现无法打开readline.h的话,安装libreadline6和libreadline6-dev


2)仿照gdbclient,在build/envsetup.sh中加入jdbclient函数

function jdbclient()
{
local MY_SRC_PATH="$1"
if [ "$MY_SRC_PATH" ] ; then
MY_SRC_PATH=$1
echo $MY_SRC_PATH
else
echo "ROOT" $OUR_ROOT
MY_SRC_PATH="app_process"
fi


local PORT="$2"
if [ "$PORT" ] ; then
PORT=$2
else
PORT=":9000"
fi


local PID
local PROG="$3"
if [ "$PROG" ] ; then
PID=`pid $3`
echo tcp$PORT jdwp$PID
adb forward "tcp$PORT" "jdwp:$PID"
echo jdbshell -sourcepath $MY_SRC_PATH -attach localhost$PORT
jdbshell -sourcepath $MY_SRC_PATH -attach localhost$PORT
sleep 2
else
echo ""
echo "please specify app you want to debug:"
echo ""
fi
}


3)启动android模拟器,运行浏览器


4)jdbclient packets/app/Browser/src/ :9000 browser
第一个参数是你要load进来的代码的地址,如果你要load多个代码(调试的时候可以看),可以
export DEBUG_SRC_PATH=
然后
jdbclient $DEBUG_SRC_PATH :9000 browser


第二个参数是attach端口,如果9000有在用,可以用其他端口
第三个参数是要调试的应用,脚本里面根据
pid browser来取得进程id,所以你要保证
adb shell ps |grep browser
能够看到对应的进程

比如我在~/.bashrc里面,设定了DEBUG_SRC_PATH

export ANDROID_SRC=/home/tom/work/gingerbread
export DEBUG_SRC_PATH=$ANDROID_SRC/frameworks/base/opengl/java:$ANDROID_SRC/frameworks/base/awt/java:$ANDROID_SRC/frameworks/base/core/java:$ANDROID_SRC/frameworks/base/location/java:$ANDROID_SRC/frameworks/base/sax/java:$ANDROID_SRC/frameworks/base/graphics/java:$ANDROID_SRC/frameworks/base/telephony/java:$ANDROID_SRC/frameworks/base/services/java:$ANDROID_SRC/frameworks/base/media/java:$ANDROID_SRC/frameworks/base/wifi/java:$ANDROID_SRC/frameworks/base/im/java:$ANDROID_SRC/dalvik/libcore/suncompat/src/main/java:$ANDROID_SRC/dalvik/libcore/nio_char/src/main/java:$ANDROID_SRC/dalvik/libcore/nio_char/src/main/java/java:$ANDROID_SRC/dalvik/libcore/security-kernel/src/main/java:$ANDROID_SRC/dalvik/libcore/security-kernel/src/main/java/java:$ANDROID_SRC/dalvik/libcore/security/src/main/java:$ANDROID_SRC/dalvik/libcore/security/src/main/java/java:$ANDROID_SRC/dalvik/libcore/archive/src/main/java:$ANDROID_SRC/dalvik/libcore/archive/src/main/java/java:$ANDROID_SRC/dalvik/libcore/awt-kernel/src/main/java:$ANDROID_SRC/dalvik/libcore/awt-kernel/src/main/java/java:$ANDROID_SRC/dalvik/libcore/luni/src/main/java:$ANDROID_SRC/dalvik/libcore/luni/src/main/java/java:$ANDROID_SRC/dalvik/libcore/math/src/main/java:$ANDROID_SRC/dalvik/libcore/math/src/main/java/java:$ANDROID_SRC/dalvik/libcore/x-net/src/main/java:$ANDROID_SRC/dalvik/libcore/openssl/src/main/java:$ANDROID_SRC/dalvik/libcore/dalvik/src/main/java:$ANDROID_SRC/dalvik/libcore/auth/src/main/java:$ANDROID_SRC/dalvik/libcore/concurrent/src/main/java:$ANDROID_SRC/dalvik/libcore/concurrent/src/main/java/java:$ANDROID_SRC/dalvik/libcore/sql/src/main/java:$ANDROID_SRC/dalvik/libcore/sql/src/main/java/java:$ANDROID_SRC/dalvik/libcore/prefs/src/main/java:$ANDROID_SRC/dalvik/libcore/prefs/src/main/java/java:$ANDROID_SRC/dalvik/libcore/xml/src/main/java:$ANDROID_SRC/dalvik/libcore/text/src/main/java:$ANDROID_SRC/dalvik/libcore/text/src/main/java/java:$ANDROID_SRC/dalvik/libcore/luni-kernel/src/main/java:$ANDROID_SRC/dalvik/libcore/luni-kernel/src/main/java/java:$ANDROID_SRC/dalvik/libcore/regex/src/main/java:$ANDROID_SRC/dalvik/libcore/regex/src/main/java/java:$ANDROID_SRC/dalvik/libcore/nio/src/main/java:$ANDROID_SRC/dalvik/libcore/nio/src/main/java/java:$ANDROID_SRC/dalvik/libcore/json/src/main/java:$ANDROID_SRC/dalvik/libcore/crypto/src/main/java:$ANDROID_SRC/dalvik/libcore/icu/src/main/java:$ANDROID_SRC/dalvik/libcore/annotation/src/main/java:$ANDROID_SRC/dalvik/libcore/annotation/src/main/java/java:$ANDROID_SRC/dalvik/libcore/junit/src/main/java:$ANDROID_SRC/dalvik/libcore/logging/src/main/java:$ANDROID_SRC/dalvik/libcore/logging/src/main/java/java:$ANDROID_SRC/dalvik/libcore-disabled/instrument/src/main/java:$ANDROID_SRC/dalvik/libcore-disabled/instrument/src/main/java/java:$ANDROID_SRC/dalvik/libcore-disabled/sound/src/main/java:packages/apps/Browser/src/


5)显示如下信息,说明调试器启动
Set uncaught java.lang.Throwable
Set deferred uncaught java.lang.Throwable
Initializing jdb ...
Group system:
(java.lang.Thread)0xc14050d0c0 <6> Compiler cond. waiting
(java.lang.Thread)0xc14050cf50 <4> Signal Catcher cond. waiting
(java.lang.Thread)0xc14050cea8 <3> GC cond. waiting
(java.lang.Thread)0xc14050cdf0 <2> HeapWorker cond. waiting
Group main:
(java.lang.Thread)0xc14001f1a8 <1> main running
(java.lang.Thread)0xc140562ad8 <21> AsyncTask #5 cond. waiting
(android.os.HandlerThread)0xc1405528f8 <20> WebViewWorkerThread running
(android.net.http.ConnectionThread)0xc14053a780 <19> http3 cond. waiting
(android.net.http.ConnectionThread)0xc14053a5a8 <18> http2 cond. waiting
(android.net.http.ConnectionThread)0xc140530f90 <17> http1 cond. waiting
(android.net.http.ConnectionThread)0xc140530da0 <16> http0 cond. waiting
(java.lang.Thread)0xc14058c008 <15> Thread-18 running
(java.lang.Thread)0xc140593370 <14> AsyncTask #4 cond. waiting
(java.lang.Thread)0xc140595dd0 <13> AsyncTask #3 cond. waiting
(java.lang.Thread)0xc14058f9f0 <12> AsyncTask #2 cond. waiting
(java.lang.Thread)0xc14055a820 <11> WebViewCoreThread running
(java.lang.Thread)0xc140591bc8 <10> AsyncTask #1 cond. waiting
(java.lang.Thread)0xc140589710 <9> CookieSyncManager running
(java.lang.Thread)0xc14050f288 <8> Binder Thread #2 running
(java.lang.Thread)0xc14050e900 <7> Binder Thread #1 running
>

6)选择感兴趣的线程
大部分应用跑在main线程里面,browser也不例外
命令 thread 线程ID

> thread 0xc14001f1a8
<1> main[1]


7)挂起线程
命令 suspend 线程ID
<1> main[1] suspend 0xc14001f1a8


8)设置断点
命令:
stop at <类>:<行号> 或
stop in <类>.<方法名>[(参数类型,...)]


<1> main[1] stop at com.android.browser.BrowserActivity:2689
Set breakpoint com.android.browser.BrowserActivity:2689

这个地方要写类名稍微麻烦一点,哪位大虾可以转化成像gdb那样,直接文件名?


9)继续执行
命令 c(ont)

<1> main[1] c
>


10)点击网页中的某一个链接
就会看到程序在BrowserActivty:2689(shouldOverideUrlLoading)处断住了
此时可以看堆栈
命令:bt/wherei
<1> main[1]bt
[1] com.android.browser.BrowserActivity.shouldOverrideUrlLoading (BrowserActivity.java:2,689), pc = 8
[2] com.android.browser.Tab$2.shouldOverrideUrlLoading (Tab.java:552), pc = 44
[3] android.webkit.CallbackProxy.uiOverrideUrlLoading (CallbackProxy.java:216), pc = 19
[4] android.webkit.CallbackProxy.handleMessage (CallbackProxy.java:323), pc = 347
[5] android.os.Handler.dispatchMessage (Handler.java:99), pc = 20
[6] android.os.Looper.loop (Looper.java:123), pc = 75
[7] android.app.ActivityThread.main (ActivityThread.java:3,683), pc = 31
[8] java.lang.reflect.Method.invokeNative (native method)
[9] java.lang.reflect.Method.invoke (Method.java:507), pc = 18
[10] com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:839), pc = 11
[11] com.android.internal.os.ZygoteInit.main (ZygoteInit.java:597), pc = 84
[12] dalvik.system.NativeStart.main (native method)


看代码
命令:l(ist)
<1> main[1] l
2,685 }
2,686 }
2,687
2,688 boolean shouldOverrideUrlLoading(WebView view, String url) {
2,689 => if (url.startsWith(SCHEME_WTAI)) {
2,690 // wtai://wp/mc;number
2,691 // number=string(phone-number)
2,692 if (url.startsWith(SCHEME_WTAI_MC)) {
2,693 Intent intent = new Intent(Intent.ACTION_VIEW,
2,694 Uri.parse(WebView.SCHEME_TEL +


看变量
命令:print
<1> main[1] print url
url = "http://m.baidu.com/img?tn=bdidxiphone&ssid=0&from=844b&bd_page_type=1&uid=wiaui_1320452293_7438&pu=sz%401320_480&itj=41"


继续执行
s(tep) – 执行当前行
step up – 执行到当前方法返回到其调用程序
s(tep)i – 执行当前指令
n(ext) – 跳过一行(跨过调用)
c(ont) – 从断点处继续执行


不说了,help是一种美德
<1> main[1] help
** command list **
connectors -- list available connectors and transports in this VM


run [class [args]] -- start execution of application's main class


threads [threadgroup] -- list threads
thread <thread id> -- set default thread
suspend [thread id(s)] -- suspend threads (default: all)
resume [thread id(s)] -- resume threads (default: all)
where [<thread id> | all] -- dump a thread's stack
wherei [<thread id> | all]-- dump a thread's stack, with pc info
up [n frames] -- move up a thread's stack
down [n frames] -- move down a thread's stack
kill <thread id> <expr> -- kill a thread with the given exception object
interrupt <thread id> -- interrupt a thread


print <expr> -- print value of expression
dump <expr> -- print all object information
eval <expr> -- evaluate expression (same as print)
set <lvalue> = <expr> -- assign new value to field/variable/array element
locals -- print all local variables in current stack frame


classes -- list currently known classes
class <class id> -- show details of named class
methods <class id> -- list a class's methods
fields <class id> -- list a class's fields


threadgroups -- list threadgroups
threadgroup <name> -- set current threadgroup


stop in <class id>.<method>[(argument_type,...)]
-- set a breakpoint in a method
stop at <class id>:<line> -- set a breakpoint at a line
clear <class id>.<method>[(argument_type,...)]
-- clear a breakpoint in a method
clear <class id>:<line> -- clear a breakpoint at a line
clear -- list breakpoints
catch [uncaught|caught|all] <class id>|<class pattern>
-- break when specified exception occurs
ignore [uncaught|caught|all] <class id>|<class pattern>
-- cancel 'catch' for the specified exception
watch [access|all] <class id>.<field name>
-- watch access/modifications to a field
unwatch [access|all] <class id>.<field name>
-- discontinue watching access/modifications to a field
trace [go] methods [thread]
-- trace method entries and exits.
-- All threads are suspended unless 'go' is specified
trace [go] method exit | exits [thread]
-- trace the current method's exit, or all methods' exits
-- All threads are suspended unless 'go' is specified
untrace [methods] -- stop tracing method entrys and/or exits
step -- execute current line
step up -- execute until the current method returns to its caller
stepi -- execute current instruction
next -- step one line (step OVER calls)
cont -- continue execution from breakpoint


list [line number|method] -- print source code
use (or sourcepath) [source file path]
-- display or change the source path
exclude [<class pattern>, ... | "none"]
-- do not report step or method events for specified classes
classpath -- print classpath info from target VM


monitor <command> -- execute command each time the program stops
monitor -- list monitors
unmonitor <monitor#> -- delete a monitor
read <filename> -- read and execute a command file


lock <expr> -- print lock info for an object
threadlocks [thread id] -- print lock info for a thread


pop -- pop the stack through and including the current frame
reenter -- same as pop, but current frame is reentered
redefine <class id> <class file name>
-- redefine the code for a class


disablegc <expr> -- prevent garbage collection of an object
enablegc <expr> -- permit garbage collection of an object


!! -- repeat last command
<n> <command> -- repeat command n times
# <command> -- discard (no-op)
help (or ?) -- list commands
version -- print version information
exit (or quit) -- exit debugger


<class id>: a full class name with package qualifiers
<class pattern>: a class name with a leading or trailing wildcard ('*')
<thread id>: thread number as reported in the 'threads' command
<expr>: a Java(tm) Programming Language expression.
Most common syntax is supported.


Startup commands can be placed in either "jdb.ini" or ".jdbrc"
in user.home or user.dir

如果要看别名映射,在终端执行

tom@tom-laptop:~/work/gingerbread$ jdbshell
usage: jdbshell [jdb args]
example: ./jdbshell -sourcepath $ANDROID_SRC_PATH -attach 6107
command alias:
c -- cont
l -- list
n -- next
r -- run
s -- step
si -- stepi
f -- step up
bt -- wherei


更多相关文章

  1. 回调函数小记
  2. Android之SQLite数据库使用
  3. Android消息机制理解
  4. Android(安卓)点击通知栏消息打开activity,并判断app是否运行
  5. Android(安卓)fragment 传值
  6. Android(安卓)Studio: License for package Android(安卓)SDK Bu
  7. android 开机启动流程分析(16)Launcher启动
  8. Android(安卓)ADB 工具使用
  9. Ubantu云服务器上配置Gradle 命令自动打包Android(安卓)Studio

随机推荐

  1. 把TextView中的文字添加阴影效果及Style
  2. android开发,修改默认界面的背景色
  3. Android ListView xml配置
  4. This Android(安卓)SDK requires Android
  5. 【30篇突击 android】源码统计 十
  6. Android SDK/ADT 历史版本下载地址
  7. android无线调试
  8. Android EditView 获取焦点 不弹出软键盘
  9. 一步一步学习androidNDK编程(hello world
  10. Android应用开发相关下载资源