用Android Studio调试Framework层代码
Android程序员不得不知的调试技巧。
本文以webview loadUrl和域名解析为例,介绍配合使用LLDB和Android Studio调试Framework代码的技巧。
java 层调试
首先需要把AOSP源码导入到Android Studio中,如果是macOS系统可以参考这篇文章。
导入后如下图所示:
调试原理
Java平台的调试是有一个规范化的标准的,那就是JPDA(Java Platform Debugger Architecture);通过 JPDA 提供的 API,开发人员可以方便灵活的搭建 Java 调试应用程序。 JPDA 主要由三个部分组成:Java 虚拟机工具接口(JVMTI),Java 调试线协议(JDWP),以及 Java 调试接口(JDI)。
调试需要堆栈、符号等信息都保存在JVM中,调试器(debugger)需要通过一种渠道获取这些信息,并通过这个渠道发送调试指令给JVM,JDWP就是调试器与JVM通信的渠道。在JVM内部有一个专门的jdwp线程,Android系统的adbd守护进程通过socket与各个虚拟机的jdwp线程进行通信,外部调试器通过主机的adb与adbd通信进而完成与jdwp的通信。具体过程如下图:
配置Debug选项
在菜单栏上依次点击Run -> Edit Configurations -> Remote,打开并配置成如下的页面
Exclued 不必要的文件夹
在断点调试时,JVM会告诉AS自己在xx.java的第xx行被断住了,AS就会定位到这个位置,但是如果有重复的文件的名的,往往会出现定位不准的情况,所以需要把不必要的文件夹排除在整个源码结构之外。打开Project Structure,做如下修改
如果遇上断点文件对不上的情况时,就手动在这里Exclued好了。
也可以直接修改aosp-root/development/tools/idegen/excluded-paths
文件中的内容,添加exclude,再运行idegen.sh
重新生成IDE代码树。
在源码处打断点
我们在WebView.java的loadUrl处打断点
点击调试按钮,你会看到Console中的提示
1
|
Connected to the target VM, address: 'localhost:8700' , transport: 'socket'
|
打开DDMS
在菜单栏上依次点击Tools ->Android -> Android Device Monitor,打开DDMS后,点击
在monitor中我们可以看到有3列,分别是
- 进程名(以包名显示)
- PID(Process ID)
- 端口号(映射端口号/实际端口号)
点击我们要调试的browser程序的那一行,会出现一只绿色的bug,表示我们的Debugger已经跟设备上的程序联系上,可以调试了。
开始调试
当在浏览器中加载一个网页时,就能触发之前设置的loadUrl的断点了,如此就可以使用各种调试手段了。
C++层调试
Android Framework中native代码的调试方法采用的是 2.2以上版本的Android Studio配合LLDB调试器。
这里以调试webview的dns查找过程为例,说明native调试的方法。
调试原理
LLDB作为Android Native层的调试工具,其原理跟gdb一样,也是采用C/S架构,通过push一个lldb-server到设备上,pc机的debugger作为lldb-client与其通信,以达到调试的效果。
C++在编译时有一个选项-g
表示编译出来的可执行文件是带有调试信息的,比如源文件、行号信息,都会存放在ELF文件中的
.debug_*
段之中, 知道了这些调试信息后,调试器配合IDE就可以定位代码了。
这里还需要保证你的符号文件和设备上真正运行的动态链接库或者可执行文件是对应的,就是同一份,不然调试信息就对不上了。
最简单的办法就是使用模拟器。我们编译完源码之后,一个主要的编译产物就是 system.img,这个 system.img会在启动之后挂载到设备的 /system 分区,而system分区包含了Android系统运行时的绝大部分可执行文件和动态链接库,而这些文件就是我们的编译输出,正好可以与编译得到的调试符号进行配合调试。模拟器有一个 -system选项用来指定模拟器使用的 system.img文件。
1
|
$ emulator -avd Nexus5-API22 -verbose -no-boot-anim -system (the path of system.img)
|
我这里的做法是使用烧录了自己编译源码的Nexus手机。
配置Debugger
这里需要新建一个Android Demo工程了,直接用AOSP源码那个工程,没有是Native Debug那个选项的。
按如下方式配置符号表,需要与设备上用的so是同一份。并且改Debug type 为Native。
符号表的添加也可以通过lldb命令行的方式添加
LLDB需要这些符号信息才能帮你定位到调试断点的代码。
配置源码到AS
当LLDB告诉AS源文件行号信息时,AS需要定位到对应的代码处,所以必须先把源文件导入到AS中,最简单的做法是建立软链接。在Android Demo工程下建立一个source文件夹,然后执行如下命令。
1
2
|
$ ln -s xx/external/chromium_org xx/source/chromium_org
$ ln -s xx/bionic/libc xx/source/libc
|
这里只是把需要用到的源文件导入进来,当然也可以把整个AOSP源码导入AS中,但是这样会比较耗时。
打断点
我在getaddrinfo.c的getaddrinfo方法处打一个断点,看看webview在加载网页时的域名解析会不会走到这里。
点击Debug按钮,当Demo程序开始LoadUrl之后,就会被Debug断住,如下是chromium域名解析线程的堆栈(这里的方法名真够长的。。。),这样我们就可以进一步了解webview加载网页时域名解析的过程了。
让我们看看其他线程在干啥,整个世界都停止了。
不足之处
目前的调试framework方案只能把java层和c++ native层的分开来做,还不能做到java层和c++ native层互相跳转的效果。虽然目前我们开发Android App用AS调试时能做大这一点,要是framework的调试也能做到这一点就好了。获取真有这样的方法,如果有知道的大神,还请赐教。
相关链接
Debugging AOSP Platform code with Android Studio - Part I - Java Debugger
Android Debugging: Old School bringup routines - Command line Java debugging with JDWP
如何调试Android Framework
如何调试Android Native Framework
在macOS 10.12 上编译 Android 5.1
转载: http://felixzhang00.github.io/2017/01/23/%E7%94%A8Android%20Studio%E8%B0%83%E8%AF%95Framework%E5%B1%82%E4%BB%A3%E7%A0%81/
用Android Studio调试Framework层代码相关推荐
- android studio 调试c/c++代码小记
使用的android studio3.0.1版本,sdk 27. 新建的测试程序,勾选了c++支持,默认有native_lib.cpp. 1.在cpp中添加了测试的native代码,提示No impl ...
- android studio 调试cocos2dx c++代码
环境: cocos2dx 2.26版本 android studio 版本 sdk 版本 1.8 ndk 版本 android-ndk-r15c 下载地址:链接:https://pan.baidu.c ...
- Android逆向笔记-使用Android Studio调试Smali代码(方式一)
这里我使用Android Studio写了这样的一个程序: 然后点下BUTTON后: 下面写下如何调试这种程序. 开发环境: win 10: 使用的模拟器是雷神模拟器: Android Studio版 ...
- [免费专栏] Android安全之动态调试APP的一些技巧「Android Studio调试」
也许每个人出生的时候都以为这世界都是为他一个人而存在的,当他发现自己错的时候,他便开始长大 少走了弯路,也就错过了风景,无论如何,感谢经历 Android安全付费专栏长期更新,本篇最新内容请前往: [ ...
- 从Android应用层及Framework层的角度分析WakeLock锁机制
从Android应用层及Framework层的角度分析WakeLock锁机制 本篇博客编写思路总结和关键点说明: 为了更加方便的读者阅读博客,通过导读思维图的形式将本博客的关键点列举出来,从而方便 ...
- android studio 自动try,Catch Try让我在Android Studio调试中感到困惑
我试图在Android Studio中调试这段代码.这一切看起来都非常简单,但尝试中的'return sb1'不允许我打破它(带有x的红点)并且说它不可执行.Catch Try让我在Android S ...
- 在Mac上使用android studio调试android手机
一.环境准备 1.安卓手机:Android版本为9 2.MacBook Pro 3.安卓数据线 二.adb介绍 1.adb概念 adb:全称是Android Debug Bridge,意思是Andro ...
- android studio调用python,Android studio中编写Python代码-2
Chaquopy 教程 Chaquopy Chaquopy的作用:使用Chaquopy在Android Studio添加Python环境,java和Python互调 目前调试后APP可以正常运行(20 ...
- android 8.1 framework层Ethernet多个以太网口切换连接实现流程
之前写过一篇<android 8.1 framework层修改以太网静态ip功能>的文章,这篇是在该基础上实现的.之前的功能,只在设备仅支持单个网口的情况下.当大佬拿来一个设备说:这个还可 ...
最新文章
- 20165328 预备作业3 Linux安装及命令
- Linux疑难杂症解决方案100篇(二)-SHELL编程函数的定义及调用
- python开发需要学什么_用Python进行web开发需要学习什么?
- perl大骆驼和小骆驼_从代码内部:骆驼路由引擎第一部分
- 【转】C++学习二 vector的用法(使用sort对于vector排序)
- MVC(Java , C# ,php)
- 服务器上出现应用程序错误。此应用程序的当前自定义错误设置禁止
- 【动态规划】LeetCode 62. Unique Paths
- Docker tomcat 多版本环境搭建
- 从pvlib入门光伏发电系统
- opencart seo优化_opencart seo 优化技巧有哪一些
- C++ 笔记 加号运算符重载
- python autoit3自动化测试_autoit-解决非标准B/S自动化测试的一个很好的思路
- 有一个已排好序的数组,要求输入一个数后,按原来排序的规律将它插入数组中——C语言
- 咏南开发框架之日志管理
- Error creating bean with name ‘sqlSessionFactory‘ defined in class path resource [applicationContext
- 小红书竞品分析_小红书与网易考拉 竞品分析报告
- iSCSI存储的配置与管理(1)
- 机器人行走背后的机械原理动画,一文看透
- lua mysql 事务_Lua 操作数据库(MySQL)