APM 相关技术交流,欢迎加我微信 knight-ZXW
通过StackVisitor实现堆栈抓取的实现DEMO, 方案细节见: https://blog.csdn.net/ByteDanceTech/article/details/119621240
目前只在Google模拟器Android 9~13 64位设备 上测试通过,未进行其他版本、机型测试
- 修复在相同线程调用suspend导致卡死的问题 (2023-01-03)
- 完善兼容性
- API 完善,数据写入文件
字节跳动sliver 采集Java函数栈实现
License: Apache License 2.0
APM 相关技术交流,欢迎加我微信 knight-ZXW
通过StackVisitor实现堆栈抓取的实现DEMO, 方案细节见: https://blog.csdn.net/ByteDanceTech/article/details/119621240
目前只在Google模拟器Android 9~13 64位设备 上测试通过,未进行其他版本、机型测试
首次安装启动是正常的,第二次启动就会出现重复的方法
首次启动的 stack_methods 数组和
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 E 在当前线程获取调用栈
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 E stack_methods[0] = 513826097944
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 E stack_methods[1] = 513826090584
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 E stack_methods[2] = 513826090584
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 E stack_methods[3] = 513825995272
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 E stack_methods[4] = 1907603128
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 E stack_methods[5] = 1904142192
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 E stack_methods[6] = 1904142192
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 E stack_methods[7] = 1907484096
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 E stack_methods[8] = 1907486528
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 E stack_methods[9] = 1904979144
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 E stack_methods[10] = 1904181072
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 E stack_methods[11] = 1904181040
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 E stack_methods[12] = 1904352864
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 E stack_methods[13] = 1905622032
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 E stack_methods[14] = 1905626352
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 E stack_methods[15] = 1905626320
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 E stack_methods[16] = 1907483904
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 E stack_methods[17] = 1891454744
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 E stack_methods[18] = 1906723528
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 E stack_methods[19] = 1908015624
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 I
long[] com.zongheng.sliver.Sliver.nativeGetMethodStackTrace(java.lang.Thread, long)
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 I
void v1.d.b()
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 I
void v1.d.b()
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 I
void com.knightboost.sliver.demo.MainActivity.onCreate(android.os.Bundle)
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 I
void android.app.Activity.performCreate(android.os.Bundle, android.os.PersistableBundle)
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 I
void android.app.Instrumentation.callActivityOnCreate(android.app.Activity, android.os.Bundle)
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 I
void android.app.Instrumentation.callActivityOnCreate(android.app.Activity, android.os.Bundle)
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 I
android.app.Activity android.app.ActivityThread.performLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent)
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 I
android.app.Activity android.app.ActivityThread.handleLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.app.servertransaction.PendingTransactionActions, android.content.Intent)
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 I
void android.app.servertransaction.LaunchActivityItem.execute(android.app.ClientTransactionHandler, android.os.IBinder, android.app.servertransaction.PendingTransactionActions)
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 I
void android.app.servertransaction.TransactionExecutor.executeCallbacks(android.app.servertransaction.ClientTransaction)
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 I
void android.app.servertransaction.TransactionExecutor.execute(android.app.servertransaction.ClientTransaction)
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 I
void android.app.ActivityThread$H.handleMessage(android.os.Message)
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 I
void android.os.Handler.dispatchMessage(android.os.Message)
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 I
boolean android.os.Looper.loopOnce(android.os.Looper, long, int)
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 I
void android.os.Looper.loop()
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 I
void android.app.ActivityThread.main(java.lang.String[])
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 I
java.lang.Object java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[])
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 I
void com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run()
2023-06-14 14:43:14.627 26901-26901 sliver pid-26901 I
void com.android.internal.os.ZygoteInit.main(java.lang.String[])
第二次启动数据输出
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 E 在当前线程获取调用栈
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 E stack_methods[0] = 2663898288
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 E stack_methods[1] = 2663871912
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 E stack_methods[2] = 2663871912
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 E stack_methods[3] = 2663895072
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 E stack_methods[4] = 1907603128
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 E stack_methods[5] = 1904142192
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 E stack_methods[6] = 1904142192
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 E stack_methods[7] = 1907484096
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 E stack_methods[8] = 1907486528
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 E stack_methods[9] = 1904979144
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 E stack_methods[10] = 1904181072
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 E stack_methods[11] = 1904181040
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 E stack_methods[12] = 1904352864
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 E stack_methods[13] = 1905622032
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 E stack_methods[14] = 1905626352
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 E stack_methods[15] = 1905626320
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 E stack_methods[16] = 1907483904
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 E stack_methods[17] = 1891454744
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 E stack_methods[18] = 1906723528
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 E stack_methods[19] = 1908015624
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 I
long[] com.zongheng.sliver.Sliver.nativeGetMethodStackTrace(java.lang.Thread, long)
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 I
void v1.d.b()
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 I
void v1.d.b()
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 I
void com.knightboost.sliver.demo.MainActivity.onCreate(android.os.Bundle)
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 I
void android.app.Activity.performCreate(android.os.Bundle, android.os.PersistableBundle)
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 I
void android.app.Instrumentation.callActivityOnCreate(android.app.Activity, android.os.Bundle)
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 I
void android.app.Instrumentation.callActivityOnCreate(android.app.Activity, android.os.Bundle)
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 I
android.app.Activity android.app.ActivityThread.performLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent)
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 I
android.app.Activity android.app.ActivityThread.handleLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.app.servertransaction.PendingTransactionActions, android.content.Intent)
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 I
void android.app.servertransaction.LaunchActivityItem.execute(android.app.ClientTransactionHandler, android.os.IBinder, android.app.servertransaction.PendingTransactionActions)
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 I
void android.app.servertransaction.TransactionExecutor.executeCallbacks(android.app.servertransaction.ClientTransaction)
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 I
void android.app.servertransaction.TransactionExecutor.execute(android.app.servertransaction.ClientTransaction)
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 I
void android.app.ActivityThread$H.handleMessage(android.os.Message)
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 I
void android.os.Handler.dispatchMessage(android.os.Message)
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 I
boolean android.os.Looper.loopOnce(android.os.Looper, long, int)
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 I
void android.os.Looper.loop()
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 I
void android.app.ActivityThread.main(java.lang.String[])
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 I
java.lang.Object java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[])
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 I
void com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run()
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 I
void com.android.internal.os.ZygoteInit.main(java.lang.String[])
2023-06-14 14:46:31.365 27568-27597 ost.sliver.demo pid-27568 D
MiuiProcessManagerServiceStub setSchedFifo
2023-06-14 14:46:39.227 27568-27595 ost.sliver.demo com.knightboost.sliver.demo
1 可以看出
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 E stack_methods[1] = 2663871912
2023-06-14 14:46:31.292 27568-27568 sliver pid-27568 E stack_methods[2] = 2663871912
这获取到的函数的指针地址有重复的,但是我并没有同一个方法调用两次
2 通过第一次函数的指针地址数组上看,自己写的类返回函数的指针的长度是12位,比如513826097944;但是非首次启动就获取不到长度为12位的函数指针;
#00 pc 0x00000000003aa704 /apex/com.android.art/lib64/libart.so (art::ThreadList::SuspendThreadByThreadId(unsigned int, art::SuspendReason, bool*)+476)
3KVagKS7J-eSYpicWVYcjA==/lib/arm64/libsliver.so (Java_com_knightboost_sliver_Sliver_nativeGetMethodStackTrace+204)
获取的堆栈中多了一些runtimeMethod方法:
<runtime method>.<runtime internal callee-save reference and argument registers method>
bool FetchStackVisitor::VisitFrame() {
void *method = ArtHelper::GetCurMethodOfVisitor(this);
auto *artMethod = static_cast<ArtMethod *>(method);
// 按照我的理解, 应该是在这里会过滤runtime Method, 不过目前没有生效
if (artMethod == nullptr || artMethod->IsRuntimeMethod()) {
return true;
}
at android.graphics.HardwareRenderer.nSyncAndDrawFrame
at android.graphics.HardwareRenderer.syncAndDrawFrame
at android.view.ThreadedRenderer.draw
at android.view.ViewRootImpl.draw
at android.view.ViewRootImpl.performDraw
at android.view.ViewRootImpl.performTraversals
at android.view.ViewRootImpl.doTraversal
at android.view.ViewRootImpl$TraversalRunnable.run
at android.view.Choreographer$CallbackRecord.run
at android.view.Choreographer.doCallbacks
at android.view.Choreographer.doFrame
at android.view.Choreographer$FrameDisplayEventReceiver.run
at android.os.Handler.handleCallback
at android.os.Handler.dispatchMessage
at android.os.Looper.loop
at android.app.ActivityThread.main
at <runtime method>.<runtime internal callee-save reference and argument registers method>
at java.lang.reflect.Method.invoke
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run
at <runtime method>.<runtime internal callee-save reference and argument registers method>
at com.android.internal.os.ZygoteInit.main
你好,我这边试了一下,发现Android 12 系统有几个机型调用SuspendThreadByThreadId会报错,分别是:
机型:HONOR/FNE-NX9
Android 12,level 31
aarch64
SIGSEGV(SEGV_MAPERR)
#00 pc 00000000001ab550 /apex/com.android.art/lib64/libart.so (art::ThreadList::SuspendThreadByThreadId(unsigned int, art::SuspendReason, bool*)+464) [arm64-v8a::289d75599f6112d5757113220599e90b]
机型:SM-A315G
Android 12,level 31
aarch64
SIGSEGV(SEGV_MAPERR)
#00 pc 000000000022f540 /apex/com.android.art/lib64/libart.so (art::ThreadList::SuspendThreadByThreadId(unsigned int, art::SuspendReason, bool*)+452) [arm64-v8a::a49c773ef6221a996ecea990e9753caa]
机型:XT2175-2
Android 12,level 31
aarch64
SIGSEGV(SEGV_MAPERR)
#00 pc 0000000000231ca8 /apex/com.android.art/lib64/libart.so (art::ThreadList::SuspendThreadByThreadId(unsigned int, art::SuspendReason, bool*)+452) [arm64-v8a::56e704c544e6c624201be2ab4933e853]
请问这个有啥排查思路吗?
获取的堆栈实际是这样(缺乏文件名和行号)
29944-29962 TAG com....looper.monitor.app D void java.lang.Thread.sleep(long, int)
29944-29962 TAG com....looper.monitor.app D void java.lang.Thread.sleep(long)
29944-29962 TAG com....looper.monitor.app D boolean com.netease.cloudmusic.APP.addIdleHandler$lambda-1(com.netease.cloudmusic.APP)
29944-29962 TAG com....looper.monitor.app D boolean com.netease.cloudmusic.APP.$r8$lambda$21O6vOVsLj7WDXPcCmA3Hd_TyE0(com.netease.cloudmusic.APP)
29944-29962 TAG com....looper.monitor.app D boolean com.netease.cloudmusic.APP$$ExternalSyntheticLambda1.queueIdle()
29944-29962 TAG com....looper.monitor.app D boolean com.netease.cloudmusic.looper.monitor.IdleHandlerDecorator$add$decorator$1.queueIdle()
29944-29962 TAG com....looper.monitor.app D android.os.Message android.os.MessageQueue.next()
而正常的getStackTrace格式是这样的
29209-29228 TAG com....looper.monitor.app D android.os.Looper.loopOnce(Looper.java:161)
29209-29228 TAG com....looper.monitor.app D android.os.Looper.loop(Looper.java:288)
29209-29228 TAG com....looper.monitor.app D android.app.ActivityThread.main(ActivityThread.java:7898)
29209-29228 TAG com....looper.monitor.app D java.lang.reflect.Method.invoke(Native Method)
29209-29228 TAG com....looper.monitor.app D com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
29209-29228 TAG com....looper.monitor.app D com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
29209-29228 TAG com....looper.monitor.app D java.lang.Thread.sleep(Native Method)
29209-29228 TAG com....looper.monitor.app D java.lang.Thread.sleep(Thread.java:450)
29209-29228 TAG com....looper.monitor.app D java.lang.Thread.sleep(Thread.java:355)
29209-29228 TAG com....looper.monitor.app D com.netease.cloudmusic.APP.addIdleHandler$lambda-1(APP.kt:70)
29209-29228 TAG com....looper.monitor.app D com.netease.cloudmusic.APP.$r8$lambda$21O6vOVsLj7WDXPcCmA3Hd_TyE0(Unknown Source:0)
29209-29228 TAG com....looper.monitor.app D com.netease.cloudmusic.APP$$ExternalSyntheticLambda1.queueIdle(Unknown Source:2)
29209-29228 TAG com....looper.monitor.app D com.netease.cloudmusic.looper.monitor.IdleHandlerDecorator$add$decorator$1.queueIdle(IdleHandlerDecorator.kt:20)```
如何修改可以保持和系统API一致呢
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.