使用jdb和gdb同时调试java native code
来源:互联网 发布:ubuntu无法联网 编辑:程序博客网 时间:2024/05/22 02:33
主要流程:
1.使用jdb启动生成的java字节码或jar包;
2.在java源码中适当的位置设置断点,如main方法;
3.使用run指令,使代码跑起来。(jdb命令只是进入调试环境,jvm还没有运行起来,当然我们的代码也没有运行起来,run指令之后,才有创建一个jvm,在进程列表中会发现多出一个java进程。)
4.另起一个终端,使用查询新生成的java进程的进程id。
5.使用gdb命令附着到上述java进程。
6.在C源码中适当的位置设置断点。
至此,两个调试都挂在了同一个jvm上。需要注意,只有两个调试器同时允许程序执行是,程序才会继续运行。
以HelloWorld为例说明:
第一至第三步如下:
$jdb HelloWorld <= 第一步正在初始化jdb...>stop in HelloWorld.main<= 第二步,设置适当的断点正在延迟断点HelloWorld.main。将在加载类后设置。>run <= 第三步, run起来运行HelloWorld设置未捕获的java.lang.Throwable设置延迟的未捕获的java.lang.Throwable>VM已启动:设置延迟的断点HelloWorld.main断点命中:"线程=main",HelloWorld.main(), 行=4bci=04 HelloWorld hw = new HelloWorld();main[1]然后另起一个终端,继续第四步至第六步
$ps -e | grep java32160pts/24 00:00:00 java$sudo gdb -p 32160GNUgdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1Copyright(C) 2014 Free Software Foundation, Inc.//××××此处有打断输出,省略Loadedsymbols for /usr/lib/jvm/jdk1.7.0_07/jre/lib/i386/libdt_socket.soReadingsymbols from/home/luyao/java/jni/HelloWorld/libHelloWorld.so...done.Loadedsymbols for /home/luyao/java/jni/HelloWorld/libHelloWorld.so <= 可以看到已经加载我们的库了0xb775f428in __kernel_vsyscall ()(gdb)break HelloWorld.c:Java_HelloWorld_print <=设置一个断点,在native的print函数前Breakpoint1 at 0xb682d58d: file HelloWorld.c, line 8.(gdb)c<= gdb释放阻塞。还需jdb调用cont命令,程序才会继续执行。Continuing.
回到第一个终端,执行cont命令
第一个终端里:
main[1]contInJava, before> native第二个终端里:
(gdb)cContinuing.[Switchingto Thread 0xb68edb40 (LWP 32164)]Breakpoint1, Java_HelloWorld_print (jenv=0xb6707d28, jobj=0xb68ed010)atHelloWorld.c:88 inti = 0; <= Nice! 程序已经断在gdb里了。(gdb)//然后就可以任意发挥了。
几个问题:
1)在上述C代码中,有一句注释掉的代码fflush(stdout);如果没有该行代码,在jdb调试器中,输出会发生乱序(native函数中的输出被延迟甚至漏掉)。单独挂gdb调试器时,没有这种问题。估计跟JVM中实现native层标准输出设备缓存的方法有关。等进一步研究JVM的实习后再来关注这个问题。
2)由于java对线程id描述的方式不同,目前无法确定从java代码调用native代码时是否发生线程切换,很大程度上感觉不会发生线程切换。在《Insidethe Java VirtualMachine》一书中只讲到从java调用native时只发生了线程栈的切换,即native代码有独立的栈,(这类似与用户态栈和内核态栈的区别)。没有线程的切换。但是这本书的编写时间较早,2000年,当时java应该还是1.3或者1.4,不知道在1.7,或者说在安卓的Dalvik虚拟机中的实现是否有不同,需进一步研究。
3)一个很困惑的问题。在启动gdb时,使用的时root权限,如果不用root权限,会报错,如下:
Attachingto process 7093Couldnot attach to process. If your uid matches the uid of the targetprocess,check the setting of /proc/sys/kernel/yama/ptrace_scope, or tryagainas the root user. For more details, see/etc/sysctl.d/10-ptrace.confptrace:不允许的操作.
不明白的是,非root下,我的uid肯定是一致的,即目标进程java的uid也是当前用户。而使用root权限启动gdb时,gdb的uid显然与目标进程java的uid不一致了
$ps -aux | grep javaluyao 7093 0.0 0.6 688660 13812 pts/24 tl+ 00:14 0:00/usr/lib/jvm/jdk1.7.0_07/jre/bin/java -Xdebug-Xrunjdwp:transport=dt_socket,address=luyao-K40IN:55455,suspend=yHelloWorldluyao 8765 0.0 0.0 6116 824 pts/7 S+ 00:20 0:00 grep--color=auto javaluyao@luyao-K40IN:~/java/jni/HelloWorld$ps -aux | grep gdbroot 8611 0.0 0.0 8312 2036 pts/12 S+ 00:19 0:00 sudo gdb-p 7093root 8612 0.8 1.4 40216 30012 pts/12 S+ 00:19 0:00 gdb -p7093luyao 8857 0.0 0.0 6116 824 pts/7 S+ 00:20 0:00 grep--color=auto gdb查看上述错误提示中提到的文档如下:
$cat /etc/sysctl.d/10-ptrace.conf#The PTRACE system is used for debugging. With it, a single userprocess#can attach to any other dumpable process owned by the same user. Inthe#case of malicious software, it is possible to use PTRACE to access#credentials that exist in memory (re-using existing SSH connections,#extracting GPG agent information, etc).##A PTRACE scope of "0" is the more permissive mode. A scopeof "1" limits#PTRACE only to direct child processes (e.g. "gdbname-of-program" and#"strace -f name-of-program" work, but gdb's "attach"and "strace -fp $PID"#do not). The PTRACE scope is ignored when a user has CAP_SYS_PTRACE,so#"sudo strace -fp $PID" will work as before. For moredetails see:#https://wiki.ubuntu.com/SecurityTeam/Roadmap/KernelHardening#ptrace##For applications launching crash handlers that need PTRACE,exceptions can#be registered by the debugee by declaring in the segfault handler#specifically which process will be using PTRACE on the debugee:# prctl(PR_SET_PTRACER, debugger_pid, 0, 0, 0);##In general, PTRACE is not needed for the average running Ubuntusystem.#To that end, the default is to set the PTRACE scope to "1". This value#may not be appropriate for developers or servers with only adminaccounts.kernel.yama.ptrace_scope= 1$cat /proc/sys/kernel//yama/ptrace_scope1
好吧,应该是ubuntu自身的安全机制导致,将/proc/sys/kernel//yama/ptrace_scope中的值改为0就可以了。
- 使用jdb和gdb同时调试java native code
- 使用eclipse/ndk-gdb对java/native code联合调试
- 使用eclipse/ndk-gdb对java/native code联合调试
- 使用eclipse/ndk-gdb对java/native code联合调试
- 使用JDB调试Java程序
- 使用JDB调试Java程序
- 使用JDB调试Java程序
- ndk-gdb对java/native code联合调试
- ndk-gdb对java/native code联合调试
- 用gdb和gdbserver调试android native code
- GDB+gdbserver 远程调试android native code
- GDB + gdbserver 远程调试android native code
- 使用jdb调试android Java层
- 使用JDB-debug调试
- jdb 调试java
- java调试命令jdb
- Android使用gdb调试native程序
- 使用ndk-gdb调试android native程序
- xapges repeat显示富域内容
- UVALive7045 多少个不同的数
- spring-jdbc直接获得POJO对象
- Effective Java学习笔记
- 大美黑龙江
- 使用jdb和gdb同时调试java native code
- 简单工厂模式、工厂方法模式、抽象工厂模式
- Android内存泄露相关资料整理
- C++ Primer Plus(第6版) 第2章编程练习
- HDU5375 格雷码
- HDU5373 整除11
- uva 1627 Team them up! 二分图 + 连通分量 + 背包
- WinForm用户控件和自定义控件的异同;
- LoadRunner 获取时间的方法