我只想从 java 虚拟机线程中获取所有转储,以查看线程锁定的内容以及等待解锁某些资源的线程。这里描述了类似的东西。我试图杀死 Zygote 进程但没有结果。
6 回答
最简单的方法是使用 DDMS,或 Eclipse 中的 ADT 插件。有关基本说明,请参阅 http://developer.android.com/tools/debugging/ddms.html。简而言之,进入设备视图,选择您感兴趣的应用程序,确保启用线程更新,然后切换到线程视图。您将在该进程中获得实时更新的线程列表。双击线程将获取当前堆栈状态的快照。
您可以在线程转储中使用全选和复制来复制和粘贴堆栈跟踪。
如果你有一个开发者/root 设备,你可以要求 Dalvik VM 转储线程堆栈,方法是SIGQUIT
向你感兴趣的应用程序进程发送一个。例如,如果你想查看日历应用程序中所有线程的堆栈,你可以这样做:
% adb shell ps | grep android.calendar
u0_a6 2596 127 912804 48296 ffffffff b6f62c10 S com.google.android.calendar
# 2596 is the process ID
% adb shell run-as com.google.android.colendar kill -3 2596
logcat 输出将显示如下内容:
I/dalvikvm( 2596): Wrote stack traces to '/data/anr/traces.txt'
所以,拉那个:
% adb pull /data/anr/traces.txt .
每次您发出进程信号时,日志都会附加到该文件中。里面可能还有其他东西,所以你需要搜索pid 2596
:
----- pid 2596 at 2012-11-27 12:48:38 -----
Cmd line: com.google.android.calendar
DALVIK THREADS:
...
这样做相对于 DDMS 线程视图的优势在于,如果线程卡在监视器上,堆栈转储将为您提供有关锁定的对象以及当前持有锁定的线程的指示。
zygote 过程在这里不相关;根据定义,它没有运行应用程序。由于它没有 JDWP 线程,并且不监听 SIGQUIT,因此无论如何您都无法从中获取堆栈跟踪。
只需在 Android Studio 中调试您手机上的应用即可;然后在“调试视图”中Alt+5
,只需按下左下角的“相机”按钮,即可获取所有堆栈跟踪的转储,包括它们持有的锁。
从答案中获取命令,并将它们放在一起,这是以下脚本。将其放入 dump.sh 文件并执行,它将找到所需的 PID,创建一个具有当前时间戳的新文件,然后将 Thread-Dump 提取到其中。当一个人有很短的时间来获取转储时,这个命令会很有用。在使用它之前,请确保将跟踪放入文件/data/anr/traces.txt
中或在脚本中替换此值。
#!/bin/sh
pid=`./adb shell ps | grep android.calendar | awk '{print $2}'`
echo $pid
f=$(date +%s%N)
echo $f
./adb shell run-as com.google.android.calendar kill -3 $pid
./adb pull /data/anr/traces.txt $f
作为替代文件名,可以f=$(date +"%T.%6N")
用来获取人类可读的时间戳。找到所需的文件会更容易。
如果您没有 root 设备并且您的应用程序不是调试版本,您仍然可以从开发人员选项生成错误报告以获取线程转储。转储位于 bugreport*.txt 文件的 VM TRACES JUST NOW 部分下。
如果您知道您怀疑的线程的 ID,它会更快。您可以通过调用以下方式获取应用程序的 PID:
adb shell ps -A | grep com.example.myapp
和线程ID:
adb shell ps -T | grep <pid>
如果您切换到 Eclipse 中的 DDMS 视图,您有一些工具可以查看线程。那是你要找的吗?
我猜你需要应用程序中的线程。为此,您可以使用 ADT eclipse 插件上的 DDMS 视图。这是文档http://developer.android.com/tools/debugging/ddms.html#thread