【问题标题】:How to get stack trace of main thread on Android 7.0?如何在 Android 7.0 上获取主线程的堆栈跟踪?
【发布时间】:2017-04-11 03:53:34
【问题描述】:

作为 Android 7.0 上的一个简单测试,Thread.getAllStackTraces() API 无法获取主线程(属于“主”线程组)的堆栈跟踪。但是主线程的堆栈跟踪可以通过Thread.currentThread().getStackTrace()获取如下。

测试代码:

    Set<Thread> threads = Thread.getAllStackTraces().keySet();
    Log.d("Test", String.format("Number of threads get by 'Thread.getAllStackTraces()': %d", threads.size()));
    for (Thread thread : threads) {
        if (thread != null) {
            Log.d("Test", String.format("[ID]: %d, [Name]: %s", thread.getId(), thread.getName()));
        }
    }
    Log.d("Test", String.format("Current thread name: %s", Thread.currentThread().getName()));
    Log.d("Test", String.format("Current group name: %s", Thread.currentThread().getThreadGroup().getName()));
    StackTraceElement[] elements = Thread.currentThread().getStackTrace();
    for (int i = 0; i < elements.length; i++) {
        Log.d("Test", String.format("main stack element[%d]: %s", i, elements[i]));
    }

Android 4.4 上的结果:

Number of threads get by 'Thread.getAllStackTraces()': 10
[ID]: 1871, [Name]: GCDaemon
[ID]: 1867, [Name]: ReferenceQueueDaemon
[ID]: 1870, [Name]: HeapTrimmerDaemon
[ID]: 1872, [Name]: Binder_1
[ID]: 1866, [Name]: JDWP
[ID]: 1868, [Name]: FinalizerDaemon
[ID]: 1869, [Name]: FinalizerWatchdogDaemon
[ID]: 1, [Name]: main
[ID]: 1873, [Name]: Binder_2
[ID]: 1865, [Name]: Signal Catcher
Current thread name: main
Current group name: main
main stack element[0]: dalvik.system.VMStack.getThreadStackTrace(Native Method)
main stack element[1]: java.lang.Thread.getStackTrace(Thread.java:580)
main stack element[2]: com.test.demo.MainActivity.onCreate(MainActivity.java:169)
main stack element[3]: android.app.Activity.performCreate(Activity.java:6117)
main stack element[4]: android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123)
main stack element[5]: android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2612)
main stack element[6]: android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2728)
main stack element[7]: android.app.ActivityThread.access$800(ActivityThread.java:179)
main stack element[8]: android.app.ActivityThread$H.handleMessage(ActivityThread.java:1579)
main stack element[9]: android.os.Handler.dispatchMessage(Handler.java:111)
main stack element[10]: android.os.Looper.loop(Looper.java:194)
main stack element[11]: android.app.ActivityThread.main(ActivityThread.java:5838)
main stack element[12]: java.lang.reflect.Method.invoke(Native Method)
main stack element[13]: java.lang.reflect.Method.invoke(Method.java:372)
main stack element[14]: com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1009)
main stack element[15]: com.android.internal.os.ZygoteInit.main(ZygoteInit.java:804)

Android 7.0 上的结果:

Number of threads get by 'Thread.getAllStackTraces()': 4
[ID]: 116, [Name]: FinalizerWatchdogDaemon
[ID]: 114, [Name]: ReferenceQueueDaemon
[ID]: 115, [Name]: FinalizerDaemon
[ID]: 117, [Name]: HeapTaskDaemon
Current thread name: main
Current group name: main
main stack element[0]: dalvik.system.VMStack.getThreadStackTrace(Native Method)
main stack element[1]: java.lang.Thread.getStackTrace(Thread.java:1566)
main stack element[2]: com.test.demo.MainActivity.onCreate(MainActivity.java:169)
main stack element[3]: android.app.Activity.performCreate(Activity.java:6664)
main stack element[4]: android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
main stack element[5]: android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2599)
main stack element[6]: android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
main stack element[7]: android.app.ActivityThread.-wrap12(ActivityThread.java)
main stack element[8]: android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)
main stack element[9]: android.os.Handler.dispatchMessage(Handler.java:102)
main stack element[10]: android.os.Looper.loop(Looper.java:154)
main stack element[11]: android.app.ActivityThread.main(ActivityThread.java:6077)
main stack element[12]: java.lang.reflect.Method.invoke(Native Method)
main stack element[13]: com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
main stack element[14]: com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)

这似乎与Android的权限有关,以获取线程信息。但 Android Device Monitor 可以获取所有线程及其详细信息。

那么有什么方法可以在 >= Android 7.0 上获取主线程堆栈吗?

感谢您的阅读和回答。

【问题讨论】:

  • 有人知道答案吗?
  • 我已经在 API 16、19、21-28 上测试了这种行为,主线程似乎没有在 API 24 和 25 上被捕获。我相信这是Android 框架,这里也提出了这个问题:issuetracker.google.com/issues/64122757
  • @fractalwrench 谢谢。

标签: android stack-trace


【解决方案1】:

我可以确认getAllStackTraces() 显然不提供主 UI 线程的堆栈跟踪,无论出于何种原因。但是,有一种方法:在任何后台线程中,您都可以调用 Looper.getMainLooper().getThread().getStackTrace()(或者只需记住 UI 代码中某处的 Thread 对象并在其上调用 getStackTrace())。

您是否正在做一些性能分析?我已经尝试过 Android Monitor,它比没用更糟糕 - 不仅 UI 非常慢,而且它捕获了完全不匹配的错误堆栈跟踪!我正在考虑编写一个非常简单的分析器,您可以随意启动和停止它,它会将分析详细信息转储到 Android 控制台中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-15
    • 2010-09-22
    • 1970-01-01
    • 1970-01-01
    • 2010-10-11
    • 1970-01-01
    • 1970-01-01
    • 2010-09-11
    相关资源
    最近更新 更多