如何调试Android源码

关于如何调试Android源码问题,网上有很多文章,大概步骤就是:

  1. 下载Android源码
  2. 在本地编译整个源码
  3. 第二步编译成功后会生成一个idea工具,可以将Android源码转换成Idea工程(这一步会生成android.iml, android.ipr文件)
  4. 在Android Studio中导入第三步生成的两个文件,即可导入整个android源码

之后各种配置sdk路径,源码路径等等,非常麻烦。另外,最麻烦的是,下载Android源码比较缓慢,并且非常占存储空间,加上编译可能会占据150-200G的磁盘空间,对于一些个人电脑(例如我的mac存储空间就只有128G, 能用于放源码的空间就更少了)。鉴于此,想到两个问题:

  1. 是否需要下载整个Android 源码?
  2. 是否一定要将源码编译一次?

首先想到的一个问题是,通常我们会调试哪些代码?对大多数人而言,只是调试framework以及system server相关的代码,而这两部分代码都是在源码的frameworks/base项目下,那么是否可以只下载这一部分代码?

为了回答上述几个问题,先来看看android程序是怎么调试的?

Android是如何调试程序的?

调试机制

Android的调试机制采用java的远程调试,每个Android进程都有一个叫做jdwp的线程,本地debugger进程通过jdwp协议与运行在真实设备或者AVD上的android进程进行通行,主要通信内容包括两方面:

  1. debugger向被调试进程发送命令(如:在某一行上设置断点,单步执行,运行到下一个断点等等)
  2. debugger从被调试进程接收程序运行数据及状态等等(例如: 程序已经运行到某个断点,当前运行行号,变量值等等)

通过jdwp协议,debugger可以控制被调试进程到运行,了解当前运行状态,行号等等,通过行号结合源码,即可实现调试。

哪些进程可以被调试

要想调试一个进程,需要被调试进程满足两个条件:

  1. 进程执行到代码包含调试信息(主要就是行号)
  2. 本地的源码必须跟被调试进程所运行的代码完全一样,否则就牛头不对马嘴了
    因此,被调试进程需要是debug的,通常编译debug的apk即可。另外,需要有与源码对应的手机(例如Google 的Nexus)。

有了行号信息,及源码,那Android Studio又是如何把他们关联起来都呢?

Android Studio如何关联源码与被调试程序?

要搞清这个问题,先来看看编译生成的debug apk是如何包含行号信息的。apk的代码最终都被打包到了dex文件中,因此,先来dex文件中看下能否找到相关信息。 下面是一个Android项目中普通Java类

package log.test.com.myapplication;

public class Test {
    public void sayHello() {
        android.util.Log.d("test", "hello");
    }
}

通过dexdump查看dex中Test类都相关信息

Class #1097            -
159016   Class descriptor  : 'Llog/test/com/myapplication/Test;'
159017   Access flags      : 0x0001 (PUBLIC)
159018   Superclass        : 'Ljava/lang/Object;'
159019   Interfaces        -
159020   Static fields     -
159021   Instance fields   -
159022   Direct methods    -
Llog/test/com/myapplication/Test;
159037   Virtual methods   -
159038     #0              : (in Llog/test/com/myapplication/Test;)
159039       name          : 'sayHello'
159040       type          : '()V'
159041       access        : 0x0001 (PUBLIC)
159042       code          -
159043       registers     : 3
159044       ins           : 1
159045       outs          : 2
159046       insns size    : 8 16-bit code units
159047       catches       : (none)
0f430c:                                        |[0f430c] log.test.com.myapplication.Test.sayHello:()V
244434 0f431c: 1a00 cd44                              |0000: const-string v0, "test" // string@44cd
244435 0f4320: 1a01 822c                              |0002: const-string v1, "hello" // string@2c82
244436 0f4324: 7120 a43c 1000                         |0004: invoke-static {v0, v1}, Landroid/util/Log;.d:(Ljava/lang/String;Ljava/lang/String;)I // method@3ca4
244437 0f432a: 0e00                                   |0007: return-void
244438       catches       : (none)
244439       positions     :
244440         0x0000 line=5
244441         0x0007 line=6
244442       locals        :
244443         0x0000 - 0x0008 reg=2 this Llog/test/com/myapplication/Test;
244444 
244445   source_file_idx   : 6457 (Test.java)

可以看到方法sayHello对应的positions

positions     :
159049         0x0000 line=5
159050         0x0007 line=6

源文件的第五行对应字节码第一行(从常量池读取"test"字符串),源文件第六行对应字节码第七行(字节码从0计数,且上述代码为简化展示,去除了构造函数相关信息), 即return-void。
从上述dex文件内容还可以看到这个类对应第源文件是Test.java,以及
Class descritor(包含包名). 那么问题来了,有了行号和文件名,是否就能在Android Studio中定位到具体到源文件呢?
这里可以有两个猜想:

  1. 从src/java目录下找。
    普通Android项目所有源码都是在src/java目录下,既然已经能拿到包
    名和文件名,应该也就能找到对应到源码文件了。
  2. Android studio会对所有到源码文件建立索引,并且同一个apk中不可能出现全限定名完全相同的类,猜测其会根据类全限定名,对源码文件建立索引。

为了验证猜想,我在src目录下新建一个子目录java2, 并建立相应对包名,然后将Test.java移动到对应到包目录下,然后启动进程,并attach到想应的进程,在Test.java中打上断点,其结果是,程序运行到断点处,依然能够停下。通过这个简单的实验,可以断定,猜想一必然是不正确的,那很可能就是猜想二了,鉴于没有好的方法去验证猜想二,暂且假定其就是对的。

开始调试源码

假定猜想二(基于类限定名建立索引)正确,也就是说,Android Studio会对工程目录下所有java文件建立索引,而不管其处于什么目录。

下载源码

绝大多数情况,我们是调试自己的程序,也就是frameworks代码,或者system server进程。这两部分代码主要都在frameworks/base项目下,因此只下载frameworks/base项目即可

导入源码
  1. 点击File->Close Project关闭当前项目,之后可以选择导入Project
屏幕快照 2017-10-29 下午11.47.55.png

选择下载好的frameworks目录, 点击下一步,选择Create project from existing sources

屏幕快照 2017-10-29 下午11.50.57.png

之后会让选择要导入的源码

屏幕快照 2017-10-29 下午11.52.44.png

这里会列出frameworks下的所有源码目录,可以只选择自己感兴趣的,这一步可以看出Android Studio会维持一堆源码目录,有了类全限定名就可以在这些目录下找到具体堆源码文件。鉴于代码本身并不是很多,我这里选择全选。之后一直下一步即可。
导入完成后,切换到Project视图,可以看到

屏幕快照 2017-10-29 下午11.55.37.png
开始调试

找到ActivityManagerService文件,在startActivityAsUser方法中打上断点(基于Android M源码 ):

屏幕快照 2017-10-29 下午11.57.35.png

由于这里调试的是system_server, 因此我们attach到system_process进程


屏幕快照 2017-10-30 上午12.00.28.png

然后,点击桌面任意一个app图标,可以看到进程在断点处停下了:

屏幕快照 2017-10-29 下午11.59.19.png

至此,我们就完成了源码调试工作,看看相比其他调试方案的优点

  1. 不需要下载全部源码,只需要下载感兴趣的模块即可。
  2. 完全不需要任何本地编译
  3. 不需要任何的配置,只需一步步导入源码即可
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容