如何利用jdb调试linux 下java程序调试

下次自动登录
现在的位置:
& 综合 & 正文
命令行启动java程序 与 jdb 调试
自己开发个Java平台,不过不是很完善,通过命令行启动java程序报"类无法找到",
对于"类无法找到"的问题,除去类不存在外,就是"类路径"没有指定好,或类路径没有相应的文件.
这次也是一样,只是并非运行的类,而是运行类所依赖的类不存在,通过jdb where指令可以输出异常dump
&&&&推荐文章:
【上篇】【下篇】博客分类:
觉得eclipse太过臃肿,或者机器资源有限,不妨试试用jdb命令行中调试java程序。先要确保adb工作正常,用adb jdwp列出支持JDPW的进程ID。
835
$ adb jdwp:
1022
用adb shell ps查看进程的信息。
system 835 793 68 ffffffff afe0c57c S system_server
radio 873 793 52 ffffffff afe0d674 S com.android.phone
app_8 876 793
ffffffff afe0d674 S android.process.media
app_7 879 793 52 ffffffff afe0d674 S android.process.acore
app_0 926 793 72 ffffffff afe0d674 S com.google.process.gapps
app_11 956 793
ffffffff afe0d674 S com.android.alarmclock
app_16 989 793 72 ffffffff afe0d674 S com.android.mms
app_23 999 793
ffffffff afe0d674 S org.broncho.powermonitor
app_19 92 16044 ffffffff afe0d674 S com.android.setupwizard
app_7 708 19204 ffffffff afe0d674 S com.android.inputmethod.pinyin
确定要调试的进程ID之后,建立网络数据转发关系。
假设这里要调试进程873。
adb forward tcp:9000 jdwp:873
设置jdb源代码路径,这里设置了android系统内的JAVA路径,如果调试自己的应用程序 ,可以加在后面。
export ANDROID_SRC=/broncho/cupcake/dev
export ANDROID_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
启动jdb
jdb -sourcepath $ANDROID_SRC_PATH -attach localhost:9000
这里的端口号9000,是由前面的tcp:9000决定。然后就可以使用jdb的各种调试命令了。方便起见可以使用jdbshell。
附:
jdb/jdbshell基本调试技巧:
jdbshell兼容所有jdb命令,只是另外加了些命令缩写、记录历史、命令自动补全和命令行编辑等功能。
1.用threads查询所有线程:
命令:
threads
结果显示示例:
组 system:
(java.lang.Thread)0xc &7& Signal Catcher 条件正在等待
(java.lang.Thread)0xc &5& HeapWorker 条件正在等待
(java.lang.Thread)0xc &3& main 条件正在等待
(java.lang.Thread)0xc &59& Binder Thread #16 正在运行
(java.lang.Thread)0xc &57& Binder Thread #15 正在运行
(java.lang.Thread)0xc &51& Binder Thread #14 正在运行
(java.lang.Thread)0xc1& Binder Thread #13 正在运行
(java.lang.Thread)0xc &53& Binder Thread #12 正在运行
(java.lang.Thread)0xc &45& Binder Thread #11 正在运行
(java.lang.Thread)0xc &49& Binder Thread #10 正在运行
(java.lang.Thread)0xc &47& Binder Thread #9 正在运行
(java.lang.Thread)0xc1& Binder Thread #8 正在运行
(java.lang.Thread)0xc &41& Binder Thread #7 正在运行
(android.os.HandlerThread)0xc &37& ContactsAsyncWorker 条件正在等待
(java.lang.Thread)0xc &35& Binder Thread #6 正在运行
(java.lang.Thread)0xc &33& Binder Thread #5 正在运行
(java.lang.Thread)0xc &31& Stk App Service 条件正在等待
(java.lang.Thread)0xc1& Binder Thread #4 正在运行
(java.lang.Thread)0xc1& Binder Thread #3 正在运行
(android.os.HandlerThread)0xc &25& AsyncQueryWorker 条件正在等待
(android.os.HandlerThread)0xc &23& Stk Icon Loader 条件正在等待
(android.os.HandlerThread)0xc &21& RilMessageDecoder 条件正在等待
(android.os.HandlerThread)0xc &19& Stk Telephony service 条件正在等待
(java.lang.Thread)0xc &17& RILReceiver 正在运行
(android.os.HandlerThread)0xc &15& RILSender 条件正在等待
(java.lang.Thread)0xc1& Binder Thread #2 正在运行
(java.lang.Thread)0xc1& Binder Thread #1 正在运行
2.选择你感兴趣的线程。
命令:
thread 0xc
结果显示示例:
&37& ContactsAsyncWorker[1]
和gdb不同的是,这里使用线程的ID,而不是线程的序号。这个问题让我折腾了好久,问了好几个做JAVA的朋友,原来他们都不用jdb。
3.暂停线程。
命令:
suspend 0xc
4.显示调用堆栈。
命令:
wherei
结果显示示例:
[1] java.lang.Object.wait (本机方法)
[2] java.lang.Object.wait (Object.java:288), pc = 3
[3] android.os.MessageQueue.next (MessageQueue.java:148), pc = 153
[4] android.os.Looper.loop (Looper.java:110), pc = 8
[5] android.os.HandlerThread.run (HandlerThread.java:60), pc = 28
5.切换调用堆栈的frame:
命令:
up [n 帧] – 向上移动线程的堆栈
down [n 帧] – 向下移动线程的堆栈
和gdb不同的时,这里指定的是要切换的frame与当前frame的偏移,而不是frame的索引。
结果显示示例:
&37& ContactsAsyncWorker[1] up
&37& ContactsAsyncWorker[2]
6.设置断点
命令:
stop at &类&:&行号& 或
stop in &类&.&方法名&[(参数类型,...)]
结果显示示例:
& stop at com.android.phone.SimContacts$ImportAllThread:124
设置 断点 com.android.phone.SimContacts$ImportAllThread:124
7.显示某个类的信息。有时要在嵌套类里设置断点,这个命令可能有帮助。
命令:
class &类 ID& – 显示已命名的类的详细信息
结果显示示例:
&class com.android.phone.SimContacts
类:com.android.phone.SimContacts
扩展: com.android.phone.ADNList
嵌套: com.android.phone.SimContacts$ImportAllThread
8.继续运行
命令:
step – 执行当前行
step up – 执行到当前方法返回到其调用程序
stepi – 执行当前指令
next – 跳过一行(跨过调用)
cont – 从断点处继续执行
9.清除断点
命令:
clear &类 ID&.&方法&[(参数类型,...)] – 清除方法中的断点
clear &类 ID&:&行& – 清除行中的断点
clear – 列出断点
10.查看源代码
命令:
list [line number|method] – 输出源代码
11.jdbshell命令缩写
command alias:
si — stepi
f — step up
bt — wherei
下载次数: 17
MyEyeOfJava
浏览: 644471 次
来自: 北京
浏览量:53491
“(2)CERT.SF:这是对摘要的签名文件。对前一步生成的M ...
分享一款代码生成器,拖拽式组件结合流式处理,很容易的访问数据库 ...
android可以选择uc浏览器,也可以下载安装证书,原生浏览 ...
你好:Android系统4.4本版以后不能是batteryin ...
为什么不能横屏录制?也即是说如果我的应用是一个横屏的应用,那么 ...
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'十一、参考
首先我们写一个最简单的小程序,但是它包含了一些最基本的面向对象要素。
class test
test(int aa,int bb)
{return a+b;}
public class hehe
public static void main(String args[])
int a = 2;
int b = 3;
int c= a+b;
System.out.println(c);
test kk=new test(1,2);
System.out.println(kk.add());
存为hehe.java后,用javac -g hehe.java进行编译。用参数g是为了产生各种调试信息,不用就无法调试。如果这里遇到问题,请参考Helloworld攻略。上面的程序是可以通过的,可以直接用java hehe运行。下面结合该例子谈谈JDB的使用。
首先键入jdb hehe 如果出现下面信息,说明系统没有找到调试的类。此时可以用java -classpath . hehe命令解决。
C:\javasource&jdb hehe
Initializing jdb...
hehe not found
如果出现一下信息,说明开始进行调试,一切正常。如果是调试Applet,则用 appletviewer -debug hehe.html命令进行调试
C:\javasource&jdb -classpath . hehe
Initializing jdb...
0xb0:class(hehe)
回想VC中的调试,应该是设置断点,然后再进行跟踪。Java中也是一样。用stop命令进行断点设置。然后用 run 命令开始调试,运行程序到断点,这里断点是设置在 main 主函数中。
& stop at hehe:18
Breakpoint set at hehe:18
running ...
Breakpoint hit: hehe.main (hehe:18)
此时可以用locals命令查看变量,用step命令进入下一条命令,也可以用单独一个stop命令来查看断点的设置情况。注意此时b还没有被赋值。
main[1] locals
Method arguments:
Local variables:
main[1] step
Breakpoint hit: hehe.main (hehe:19)
当运行到&System.out.println()&函数时,会出现以下提示:
main[1] step
Breakpoint hit: java.lang.ClassLoader.loadClass (ClassLoader:247)
这个是因为我们跟踪进去了&println&方法,我们一般没有必要这样做,此时可以用next跳过该方法进入到下一条一句。step的含义是进入函数跟踪,next是转入下一条语句执行。我们随时可以键入 locals 和 list 命令来查看变量值和当前运行的代码。下面箭头指到地方即为当前程序运行到的地方。
main[1] next
Breakpoint hit: hehe.main (hehe:20)
main[1] list
int a = 2;
int b = 3;
int c= a+b;
System.out.println(c);
test kk=new test(1,2);
System.out.println(kk.add());
接下来的问题自然是如何查看对象。当程序运行到&new&命令处时,键入locals,可以看到
main[1] step
Breakpoint hit: test. (test:5)
main[1] list
class test
test(int aa,int bb)
main[1] locals
Method arguments:
Local variables:
this = test@64fd6722
可以看到此时显示的变量值是类&test&中构造函数中的变量值。&this&对象即为当前构造的对象。可以用&dump&命令进行查看。
main[1] dump this
this = (test)0x11a {
也可以在&main&函数中用&dump kk&和&print&命令进行对象查看
main[1] dump kk
kk = (test)0x11a {
main[1] print kk
kk = test@64fd6722
main[1] print kk.a
main[1] print kk.b
最后键入&cont&命令,如果没有其他断点,程序就直接运行完毕退出。调试结束。
main[1] cont
& Current thread "main" died. Execution continuing...
hehe exited
上述操作中的断点都是设置在&main&函数中的,如果要设置在调用的类方法中,则要用&stop in yourclassname.functionname&命令来进行设置,比如说:
& stop in test.add
Breakpoint set in test.add
running ...
Breakpoint hit: test.add (test:11)
main[1] list
{return a+b;}
public class hehe
public static void main(String args[])
这样的话,我们已经可以在程序中的几乎所有需要地方的地方进行断点设置并进行跟踪,查看变量。
JDB还有很多的调试手段,除了上面那些最常用的,其他很重要的还有clear清除断点,use设置源程序路径,memory显示当前内存使用状况,gc强制进行内存回收,!!重复上面的命令,thread设置当前线程,quit和exit退出jdb等,还有远程调试等内容,都很有用。这里就不一一介绍了。
阅读(...) 评论()在 SegmentFault,解决技术问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。
一线的工程师、著名开源项目的作者们,都在这里:
获取验证码
已有账号?
问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
如何使用命令行调试由 gradle 命令构建的 Java 项目?这是构建前的目录结构:
其中 build.gradle 的内容是:
apply plugin: 'java'
HelloWorld.java 的内容是:这是用 gradle 构建完之后的项目结构:这是运行命令和运行结果:
请问如何使用命令行调试这个 java 项目?
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
你的意思是有命令行调试工具吗?jdb可以试试
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
运行时加选线 -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=xxxx 启动jdwp然后使用jdb -attach ip:端口号 本机就是127.0.0.1然后就可以用jdb命令了 比如 stop at 是下断点什么的要看帮助输入help
具体可参考
分享到微博?
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:

我要回帖

更多关于 java程序调试步骤 的文章

 

随机推荐