如何阅读 Dalvik SIGQUIT 输出

译自国外的一个博客,有不准确的地方请见谅。先上个例子:

 "Thread-10" prio=5 tid=8 NATIVE
      | group="main" sCount=0 dsCount=0 obj=0xf5f77d60 self=0x9f8f248
      | sysTid=22299 nice=0 sched=0/0 cgrp=[n/a] handle=-256476304
      | schedstat=( 153358572 709218 48 ) utm=12 stm=4 core=8
      at MyClass.printString(Native Method)
      at MyClass$1.run(MyClass.java:15)
术语

首先先认识几个术语,因为 ”thread“ 有很多不同的含义必须先了解:

  • Thread:代表 java.lang.Thread
  • pthread:代表C库中一个本地 thread 的抽象
  • native thread:代表由内核创建的响应 clone(2) 系统调用的东西
  • Thread*:代表 在VM 中的包括所有上述内容的 C 结构体
  • thread:代表一个 thread 的抽象表示
"Thread-10" prio=5 tid=8 NATIVE

首先是 thread 名,被包含在一对双引号里。如果你赋予了一个 Thread 构造函数名字,那么它就是你在这里所看到的。否则它会是一个在 Thread 中的 static 的 int 值, 也就是单调递增的一个 thread id,用来给每个 thread 一个唯一的名字。这些 thread id 在给定的 VM 中不会被重复使用(虽然理论上来说你可以用 int 去包装)。

接下来就是 thread 的优先级。这是 Thread 的优先级表示,与 getPriority
,setPriority 和 MIN_PRIORITY,NORM_PRIORITY,MAX_PRIORITY等常数对应。

再接着就是 thread 的 thin lock 的 id,用 ”tid“ 表示。如果你很熟悉 Linux,它肯会使你困惑,因为它不是 gettid(2) 系统调用中的 tid,而是 VM 的锁实现所使用的一个整数。这些 id 来自一个很小的池,所以当线程创建和销毁的时候可以重复使用,而且都是比较小的整数。

最后的就是 thread 的状态。这些状态与 Thread 的线程状态非常相似,但是有所扩展。它们当然会随着版本改变。一般 Dalvik 使用以下的状态 (在vm/Thread.h 中的 enum ThreadStatus 中)。

/* these match up with JDWP values */
    THREAD_ZOMBIE       = 0,        /* TERMINATED */
    THREAD_RUNNING      = 1,        /* RUNNABLE or running now */
    THREAD_TIMED_WAIT   = 2,        /* TIMED_WAITING in Object.wait() */
    THREAD_MONITOR      = 3,        /* BLOCKED on a monitor */
    THREAD_WAIT         = 4,        /* WAITING in Object.wait() */
    /* non-JDWP states */
    THREAD_INITIALIZING = 5,        /* allocated, not yet running */
    THREAD_STARTING     = 6,        /* started, not yet on thread list */
    THREAD_NATIVE       = 7,        /* off in a JNI native method */
    THREAD_VMWAIT       = 8,        /* waiting on a VM resource */
    THREAD_SUSPENDED    = 9,        /* suspended, usually by GC or debugger */
  • ZOMBIE :一般你不会看到 ZOMBIE 状态,因为线程只有当被拆卸的时候才会是这个状态。

  • RUNNING:RUNNING 的描述有点不准确,通常使用的词是 ”RUNNABLE“,因为当前 thread 是否真正在 core 上被调度并不受 VM 的管理。

  • TIMED_WAIT:与 Object.wait(long, int) 对应。注意,Thread.sleep 和 Object.wait(long) 目前都代表它。

  • WAIT:表示通过 Object.wait() 的没有延迟的等待、

  • MONITOR:表示 thread 试图在 monitor 上同步而被阻塞,要么是因为一个同步代码块,要么是一个同步方法(或者理论上来说,在一个调用 JNIEnv:MonitorEnter 上)。

  • INITIALIZING ,STARTING:当前thread 启动的实现。作为一个app 开发者,你可能会将这两个状态一起看成”运行我的代码还为时过早“。

  • NATIVE:表示 thread 在一个本地方法中。

  • VMWAIT:表示 thread 正在试图获取一些对管理的代码不可见资源而被阻塞,例如一个内部锁(即一个 phtread_mutex)。

  • SUSPENDED:表示 thread 已经被告知停止运行并且正在等待被允许继续执行,尤其是作为一个 app 开发者,当有个 GC 在运行或者一个 debugger 连接的时候你会看见它。

本例中没有显示,但是一个 deamon thread 会有一个 ”daemon“ 在第一行的后面。

| group="main" sCount=0 dsCount=0 obj=0xf5f77d60 self=0x9f8f248
  • group:线程所属 ThreadGroup 名,被双引号括起来。
  • sCount (suspension count):是请求这个 thread 挂起的数量。
  • dsCount:来自 debugger 的请求这个 thread 挂起的数量。

sCount 与 dsCount 两个整数都与线程挂起有关,分开记录这两个值是因为如果一个 debugger 断开连接,那么 sCount 则可以被正确地重置(因为可能会有非 debugger 的挂起请求,我们不能在一个 debugger 断开时仅仅重置 sCount 为 0)。
obj:Thread 的地址。
self:Thread* 的地址。除非将 gdb(1) 附加到正在运行的dalvikvm进程,否则这些地址都不可能对您有用。

| sysTid=22299 nice=0 sched=0/0 cgrp=[n/a] handle=-256476304
  • sysTid:kernel 的 thread id。如果你在 /proc/pid/task/tid目录下你可以使用它。通常这是这行唯一有用的东西。
  • nice:kernel 对于进程的 nice 值。这是作为 getpriority(2) 系统调用的返回值。
  • sched:pthread 调度策略和优先级。作为pthread_getschedparam(3) 系统调用的返回值。
  • cgrp:thread 调度组的名字,从 /proc 下对应的 cgroup 文件拉取。
  • handle:pthread对应这个线程的 pthread_t。除非你使用 gdb(1),否则很少被使用。
| schedstat=( 153358572 709218 48 ) utm=12 stm=4 core=8

schedstat:schedstat 数据是从 /proc 下的每个进程的 schedstat 文件中拉取的。它的格式被记录在 Linux kernel 树中(Documentation/scheduler/sched-stats.txt)。

  1. time spent on the cpu
  2. time spent waiting on a runqueue
  3. # of timeslices run on this cpu

如果kernel 不支持的话,你会看见 ”schedstat=( 0 0 0 ) “.

  • utm:user-mode jiffies
  • stm:kernel-mode jiffies

这些字段对应着 /proc 下每个线程的 stat 文件中额 utime 和 stime 字段。这些数字通常不会单独使用,除了在看哪些应用占用了所有的CPU时间。

  • core:芯片中 CPU 的数量。

源自 http://elliotth.blogspot.com/2012/08/how-to-read-dalvik-sigquit-output.html

你可能感兴趣的:(如何阅读 Dalvik SIGQUIT 输出)