安卓Activity在finish后出现黑屏, 大概率是因为主线程卡死。 抓trace和logcat。
04-16 16:18:17.359 W/m.lianjia.beik(30714): Long monitor contention with owner Binder:30714_6 (32307) at void java.lang.Object.wait(long, int)(Object.java:-2) waiters=0 in android.content.ComponentName com.ke.ljplugin.component.service.server.PluginServiceServer$Stub.startService(android.content.Intent, android.os.Messenger) for 5.996s
04-16 16:18:17.360 W/m.lianjia.beik(30714): Current owner stack:
04-16 16:18:17.360 W/m.lianjia.beik(30714): (no managed stack frames)
04-16 16:18:17.360 W/m.lianjia.beik(30714): Contender stack:
04-16 16:18:17.360 W/m.lianjia.beik(30714): at com.ke.ljplugin.component.service.server.PluginServiceServer$Stub.startService(PluginServiceServer.java:554)
04-16 16:18:17.360 W/m.lianjia.beik(30714): at com.ke.ljplugin.component.service.PluginServiceClient.startService(PluginServiceClient.java:106)
04-16 16:18:17.360 W/m.lianjia.beik(30714): at com.ke.loader2.PluginContext.startService(PluginContext.java:516)
04-16 16:18:17.360 W/m.lianjia.beik(30714): at com.lianjia.sdk.im.service.IMService.startIMService(link:100)
04-16 16:18:17.360 W/m.lianjia.beik(30714): at com.lianjia.sdk.im.IMManager.initIMService(link:316)
04-16 16:18:17.360 W/m.lianjia.beik(30714): at com.lianjia.sdk.im.IMManager.syncData(link:263)
04-16 16:18:17.360 W/m.lianjia.beik(30714): at com.lianjia.sdk.im.IMManager.access$200(link:51)
04-16 16:18:17.360 W/m.lianjia.beik(30714): at com.lianjia.sdk.im.IMManager$2.call(link:250)
04-16 16:18:17.360 W/m.lianjia.beik(30714): at com.lianjia.sdk.im.IMManager$2.call(link:240)
04-16 16:18:17.360 W/m.lianjia.beik(30714): at rx.internal.util.ActionSubscriber.onNext(ActionSubscriber.java:39)
04-16 16:18:17.360 W/m.lianjia.beik(30714): at rx.observers.SafeSubscriber.onNext(SafeSubscriber.java:134)
04-16 16:18:17.360 W/m.lianjia.beik(30714): at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.call(OperatorObserveOn.java:224)
04-16 16:18:17.360 W/m.lianjia.beik(30714): at rx.android.schedulers.LooperScheduler$ScheduledAction.run(LooperScheduler.java:107)
04-16 16:18:17.360 W/m.lianjia.beik(30714): at android.os.Handler.handleCallback(Handler.java:873)
04-16 16:18:17.360 W/m.lianjia.beik(30714): at android.os.Handler.dispatchMessage(Handler.java:99)
04-16 16:18:17.360 W/m.lianjia.beik(30714): at android.os.Looper.loop(Looper.java:201)
04-16 16:18:17.360 W/m.lianjia.beik(30714): at android.app.ActivityThread.main(ActivityThread.java:6806)
04-16 16:18:17.360 W/m.lianjia.beik(30714): at java.lang.reflect.Method.invoke(Native method)
04-16 16:18:17.360 W/m.lianjia.beik(30714): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
04-16 16:18:17.360 W/m.lianjia.beik(30714): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
04-16 16:18:17.360 W/m.lianjia.beik(30714):
04-16 16:18:17.388 I/Choreographer(30714): Skipped 361 frames! The application may be doing too much work on its main thread.
日志示例:“
04-15 14:11:33.634 I/Choreographer(23776): Skipped 365 frames! The application may be doing too much work on its main thread.
”
触发条件: SKIPPED_FRAME_WARNING_LIMIT值为30, 即丢了30帧时打印这行日志, 对应0.5秒。
void doFrame(long frameTimeNanos, int frame) {
。。。
if (skippedFrames >= SKIPPED_FRAME_WARNING_LIMIT) {
Log.i(TAG, "Skipped " + skippedFrames + " frames! "
+ "The application may be doing too much work on its main thread.");
}
滑动滚轮在main里找宽度大的条目(每种颜色代码一个函数), 宽度越大说明占用CPU越长。 点击图像里的条目可以索引到下面的函数。
PS:滑动鼠标中间的滚轮可以放大或缩小柱状图。
关注核心指标:
Cpu Time/Call, 函数执行时长
Real Time/Call, 占用CPU时间,包括切换、阻塞时间。 Calls+Recur/Call, 调用次数(含递归)总次数
例如图片里startService的Cpu Time等于12.964ms, 但Real Time等于6013.609ms, 差距非常大。 原因在于startService使用了同步机制,即阻塞等待。 Logcat的第一句java.lang.Object.wait…, 当主线程卡死但没到ANR程度时, logcat里提示丢帧“too much work on its main thread"。
打印日志后可以搜索“too much”关键字。