2017-04-11 167 views
0

作爲Android 7.0上的簡單測試,Thread.getAllStackTraces() API無法獲取主線程(屬於「主」線程組)的堆棧跟蹤。但是主線程的堆棧軌跡可以通過Thread.currentThread().getStackTrace()得到。如何獲取Android 7.0主線程的堆棧跟蹤?

測試代碼:

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 4.4的

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設備監視器可以獲取所有線程及其詳細信息。

那麼有沒有什麼辦法可以讓主線程堆棧在android = 7.0上?

感謝您的閱讀和解答。

+0

任何人都知道答案? – Jalen

回答

0

我可以證實,無論出於何種原因,顯然getAllStackTraces()都不會爲主UI線程提供堆棧跟蹤。但是,有一種方法:在任何後臺線程中,您可以調用Looper.getMainLooper().getThread().getStackTrace()(或者只需記住UI代碼中的某個Thread對象,然後在該代碼上調用getStackTrace())。

你也許在做一些性能分析?我嘗試過Android監視器,它比無用的更糟糕 - 不僅UI非常慢,而且捕獲完全不匹配的錯誤堆棧痕跡!我正在考慮編寫一個非常簡單的吮吸式分析器,您可以隨意啓動和停止,只需將分析詳細信息轉儲到Android控制檯即可。