DDMS的使用
Android Studio 中包含一个叫做 Dalvik Debug Monitor Server (DDMS) 的调试工具, 它具备端口映射,屏幕截图,获取设备线程和堆信息、日志、进程、无线状态信息等多个功能,还可以模拟通话、短信、位置信息等等。本文会对DDMS的功能做一个适当的介绍,关于DDMS全面详尽的功能和特性请自行了解。
运行DDMS
DDMS 被整合进了 Android Studio,如果要使用它,要先运行 Android Device Monitor 然后点击DDMS。DDMS可以在模拟器或者Android设备上工作,如果电脑同时连接了设备又打开了模拟器,那么DDMS会优先选择模拟器。
DDMS 如何与调试工具交互
在Android系统中,每个应用都运行在自己的进程里,每个进程都运行在自己的虚拟机(VM)中,每个VM都会暴露出一个特殊的端口,调试工具通过这个端口可以连接进程。
当DDMS启动时,它会先连接adb,当设备连接时,VM监听服务会在adb和DDMS之间被创建,当设备中的一个VM启动或者终止时,这个服务会向DDMS发送通知。当VM运行时,DDMS会通过adb检索VM的进程ID(pid),并通过设备中的adb守护进程(adbd)连接VM调试工具,此时DDMS会告知VM可以使用自定义协议。
DDMS为设备中的每个VM分配了一个调试端口, 第一个可调式的VM端口为8600,然后为8601,以此类推,当调试工具连接了其中一个端口时,所有的通信会从这个端口关联的VM转向调试工具,一个调试工具只能连接一个端口,但DDMS可以使其连接多个端口。
默认情况下,DDMS也会监听另外一个调试端口——DDMS基本端口(默认为8700),这个端口是一个映射,它可以接收任意一个VM的调试端口的通信并将其转到调试工具上的8700端口,这就可以让我们在将调试工具连接到8700端口之后对所有设备上的VM进行调试,而当前8700端口通信连接的哪个VM取决于我们在DDMS设备视图中选择的是哪个进程。
下面的截图显示了一个典型的DDMS窗口,如果你从命令行开启的DDMS,窗口会略微有些不同,但大多数功能是相同的。注意当前选择的那个com.android.systemui进程,它的调试端口为8606,同时也映射到了8700端口之上。
![](https://developer.android.com/images/debug-ddms.png)
图 1. DDMS屏幕截图
如果使用的命令行开启的DDMS,请阅读 Configuring your IDE to attach to the debugging port 以获取更多信息。
小贴士: 你可以在File > Preferences中设置DDMS的个人偏好,其保存在 $HOME/.android/ddms.cfg
已知的用 Dalvik 调试会遇到的问题
在Dalvik VM中调试一个应用应该和在其他VM中相同,然而,在同步代码外的单步操作中,当前行的cursor会直接跳到最后一行。 (不知道什么意思,贴上原文)。
Known debugging issues with Dalvik
Debugging an application in the Dalvik VM should work the same as it does in other VMs. However, when single-stepping out of synchronized code, the "current line" cursor may jump to the last line in the method for one step.
下面会描述如何使用DDMS以及其中各个标签页、视图的使用,Android Studio版本和命令行版本的UI稍有不同,但功能相同,如何运行DDMS请看之前所讲的。
查看进程的堆使用情况
DDMS可以查看一个进程正在使用多少堆内存,在应用运行时,这个信息对于追踪一个时间点的堆使用很有用。
查看进程堆使用情况的步骤:
- 在 Devices 标签中,选择希望查看堆信息的进程。
- 点击 Update Heap 按钮以开启这个进程的堆信息更新。
- 在 Heap 标签中,点击 Cause GC 以调用垃圾回收,这个可以收集堆数据,当这个操作完成后,你会看到一组object类型和每个类型分配到的内存,再次点击 Cause GC 可以更新数据。
- 点击列表中的一个 object 类型可以看到这个类型中不同内存大小的对象及其数量。
追踪对象的内存分配
DDMS 提供了一个功能来追踪对象被分配了多少内容,以及查看哪些类和线程分配了这些对象。这可以在实际中让我们追踪当执行应用中的功能时,对象在哪里被创建以及创建了多少,在应用性能受到内存使用影响时,这个信息十分有用。
追踪对象内存分配的步骤:
- 在 Devices 标签中, 选择希望追踪内存分配的进程。
- 在 Allocation Tracker 标签页中,点击 Start Tracking 按钮以开启追踪,这时开始,你在应用中做的所有的事情都会被追踪到。
- 点击 Get Allocations 来查看自从点击 Start Tracking 按钮之后分配到的对象列表,再次点击 Get Allocations 可以将新分配的对象添加到列表中。
- 如果需要停止追踪或清除数据重新开始,点击 Stop Tracking button。
- 点击列表中的一行可以查看更细节的信息,例如分配这个对象的调用的方法及行数。
操作模拟器或设备的文件系统
DDMS 提供了一个 File Explorer 标签来让我们查看,复制或删除设备中的文件,这个功能对于检查应用创建的文件、从设备中复制文件出来、复制文件到设备中很有用。(使用adb pull或者adb push也可以)
文件系统操作步骤:
- 在 Devices 标签中,选择需要查看文件系统的模拟器或设备。
- 如果要从设备中复制文件出来,先在 File Explorer 中定位到文件再点击 Pull file 按钮。
- 如果要复制文件到设备中,就在 File Explorer 标签中点击 Push file 。
检查线程信息
DDMS 中的线程信息给我们展示了当前选择的进程中正在运行的线程。
- 在 Devices 标签中,选择需要查看线程信息的进程。
- 点击 Update Threads 按钮。
- 在 Threads 标签中, 你可以查看选择的进程的线程信息。
方法分析
方法分析是追踪方法核心调度的一个手段,例如可以追踪方法调用,执行时间,某个调用的执行时间。如果需要更细的控制分析数据的手机,需要使用 startMethodTracing()
和 stopMethodTracing()
方法,更多关于生产trace log的信息请查阅 Profiling and Debugging UIs。
在你使用 DDMS开启方法分析之前,需要知道以下限制:
- Android 2.1 及更早的版本必须有 SD 卡并且应用必须有写SD卡的权限。
- Android 2.2 级之后的版本不需要有 SD 卡,trace log会直接传到开发的机器中(PC或服务器)。
方法分析的步骤:
- 在 Devices 标签中,选择需要开启方法分析的进程。
- 点击 Start Method Profiling 按钮。
- 在 Android 4.4 及之后版本中,选择 trace-based profiling 或 sample-based profiling 其中一个并设置时间间隔,之前的版本只有 trace-based profiling 时可用的。
- 和应用交互以调用你想分析的方法。
- 点击 Stop Method Profiling 按钮,DDMS会停止分析应用并打开在点开始和停止之间调用的方法信息的 Traceview 。
网络通信工具的使用
在 Android 4.0 中,DDMS (Dalvik Debug Monitor Server) 包含一个网络使用细节标签页,它可以追踪应用在什么时候发送了网络请求,使用这个工具,我们可以监视应用传输数据的时间以及如何传送的数据,并会自动完善潜在的代码。我们也可以在使用之前通过申请一个网络包的标签来区分不同的通信类型。
这些标签显示在DDMS中的堆区域图表中,如图2所示:
![](https://developer.android.com/images/developing/ddms-network.png)
图2. 网络使用标签
通过监视每次连接时数据传送的频率及大小,可以确认应用的使用情况以使应用更加高效,通常,我们应该观察short spikes,它会有延迟或者会在获得之前推迟传送。
为了更好地确认造成传送spikes的原因,我们可以使用 TrafficStats
API ,使用其中的 setThreadStatsTag()
allows 方法可以让我们为发生在线程中的网络通信打标签,为单独的包打标签或者去掉标签可以使用 tagSocket()
和 untagSocket()
。例:
TrafficStats.setThreadStatsTag(0xF00D); TrafficStats.tagSocket(outputSocket); // Transfer data using socket TrafficStats.untagSocket(outputSocket);
开发环境中的 URLConnection
APIs 会自动为已经打了标签的(可以用getThreadStatsTag()
方法来确认)内部的包打上标签,这些API在激活的线程池刷新时会为包正确的打标签/解除标签。下面的例子中,setThreadStatsTag()
设置了激活的标签为 0xF00D
。每个线程中只能有一个激活的标签, 这个标签是一个值,在 getThreadStatsTag()
方法中可以返回然后在HTTP客户端中使用可以给包打标签,调用 clearThreadStatsTag()
可以清楚标签。
TrafficStats.setThreadStatsTag(0xF00D); try { // Make network request using your http client. } finally { TrafficStats.clearThreadStatsTag(); }
Android 4.0支持包的标签,但实际上必须要在Android 4.0.3或更高版本上才可以显示。
LogCat的使用
LogCat 被整合进了 DDMS,它可以输出用Log类打印出的信息以及其他系统信息,例如发生异常时的stack trace,查阅 Reading and Writing Log Messages以了解更多关于LogCat中如何打Log的信息。
当你查看Log时,可以使用DDMS中LogCat中功能来过滤信息,按钮如下:
- Verbose
- Debug
- Info
- Warn
- Error
也可以设置自己的过滤器,比如标签、进程号等等,标签的增删改可以让我们更好的管理过滤器。
模拟电话业务功能以及位置信息
图1中的 Emulator Control 标签已经不再支持了,现在是要使用 Android Emulator 来实现这些功能。