jdb 包含在jdk,使用jdb 之前需要先配置jdk的环境变量。
jdb 常用于三方apk 无源码动态调试,与其配合的工具为 baksmali、apkanalyser,
通过apkanalyser打印堆栈,理清楚正常情况下的代码流程。
使用baksmali,获取 相关 的方法名,变量名,
使用jdb 动态调试,获取这些值。
jdb调试流程为:
1、打开ddms 获取需要调试进程的端口号
或者 使用命令,建立对应进程的调试桥(有时好使,有时不好使,不知道为啥,望有人指点一下)
adb jdwp 查看可调试的 pid
netstat -nlt|grep locals_port 查看端口是否被占用,被占用了换一个。
adb forward tcp:locals_port jdwp:<pid> 使用本地端口调试 指定pid
2、linux 下: jdb -attach 127.0.0.1:port
window 下为: jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=???
3、进入jdb调试内, 结合之前apkanalyser 获取到的堆栈 ,打断点,也可以在jdb中调用
classes 列举出已经加载的类
class <class id> -- 显示指定类的详细信息
methods <class id> -- 显示指定的 所有继承、实现、自定义的方法
fields <class id> -- 列出类的字段
获取到需要调试的方法,使用stop in class-name.method 或 stop in at class-name:line 在相应处打断点
4、正常操作apk,执行到断点处会停下来,
可以使用where 获取断点之前的调用栈,
使用locals 获取当前的变量值,
使用print 输出一个表达式的值
使用cont 恢复运行
使用step 单步调试。
5、jdb 调试 内部类
stop in com.android.server.类$内部类.方法
常用的就这些,也可以在jdb中使用? 查看详细文档。
6、jdb 调试IBinder
android 中都是通过Binder 进行通信的,每一个 aidl 文件都会有他的 自动实现类,通过jdb 来调试他的最终实现类:
例如:
stop in com.example.chengli.myapplication.IMyAidlInterface$Stub$Proxy.basicTypes
ps:
需要注意的是:
com.example.chengli.myapplication.IMyAidlInterface$Stub 会在程序运行时加载进入内存
最终实现类
com.example.chengli.myapplication.IMyAidlInterface$Stub$Proxy 会在binder 成功后加载进入内存