亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > Android > 正文

通過Android trace文件分析死鎖ANR實例過程

2020-04-11 12:09:45
字體:
來源:轉載
供稿:網友
對于從事Android開發的人來說,遇到ANR(Application Not Responding)是比較常見的問題。一般情況下,如果有ANR發生,系統都會在/data/anr/目錄下生成trace文件,通過分析trace文件,可以定位產生ANR的原因。產生ANR的原因有很多,比如CPU使用過高、事件沒有得到及時的響應、死鎖等,下面將通過一次因為死鎖導致的ANR問題,來說明如何通過trace文件分析ANR問題。

對應的部分trace文件內容如下:
"PowerManagerService" prio=5 tid=24 MONITOR
| group="main" sCount=1 dsCount=0 obj=0x41dd0eb0 self=0x5241b218
| sysTid=567 nice=0 sched=0/0 cgrp=apps handle=1380038664
| state=S schedstat=( 6682116007 11324451214 33313 ) utm=450 stm=219 core=1
at com.android.server.am.ActivityManagerService.broadcastIntent(ActivityManagerService.java:~13045)
- waiting to lock <0x41a874a0> (a com.android.server.am.ActivityManagerService) held by tid=12 (android.server.ServerThread)
at android.app.ContextImpl.sendBroadcast(ContextImpl.java:1144)
at com.android.server.power.PowerManagerService$DisplayBlankerImpl.unblankAllDisplays(PowerManagerService.java:3442)
at com.android.server.power.DisplayPowerState$PhotonicModulator$1.run(DisplayPowerState.java:456)
at android.os.Handler.handleCallback(Handler.java:800)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:194)
at android.os.HandlerThread.run(HandlerThread.java:60)
"Binder_B" prio=5 tid=85 MONITOR
| group="main" sCount=1 dsCount=0 obj=0x42744770 self=0x58329e88
| sysTid=3700 nice=-20 sched=0/0 cgrp=apps handle=1471424616
| state=S schedstat=( 1663727513 2044643318 6806 ) utm=132 stm=34 core=1
at com.android.server.power.PowerManagerService$DisplayBlankerImpl.toString(PowerManagerService.java:~3449)
- waiting to lock <0x41a7e420> (a com.android.server.power.PowerManagerService$DisplayBlankerImpl) held by tid=24 (PowerManagerService)
at java.lang.StringBuilder.append(StringBuilder.java:202)
at com.android.server.power.PowerManagerService.dump(PowerManagerService.java:3052)
at android.os.Binder.dump(Binder.java:264)
at android.os.Binder.onTransact(Binder.java:236)
at android.os.IPowerManager$Stub.onTransact(IPowerManager.java:373)
at android.os.Binder.execTransact(Binder.java:351)
at dalvik.system.NativeStart.run(Native Method)
"android.server.ServerThread" prio=5 tid=12 MONITOR
| group="main" sCount=1 dsCount=0 obj=0x41a76178 self=0x507837a8
| sysTid=545 nice=-2 sched=0/0 cgrp=apps handle=1349936616
| state=S schedstat=( 15368096286 21707846934 69485 ) utm=1226 stm=310 core=0
at com.android.server.power.PowerManagerService.isScreenOnInternal(PowerManagerService.java:~2529)
- waiting to lock <0x41a7e2e8> (a java.lang.Object) held by tid=85 (Binder_B)
at com.android.server.power.PowerManagerService.isScreenOn(PowerManagerService.java:2522)
at com.android.server.wm.WindowManagerService.sendScreenStatusToClientsLocked(WindowManagerService.java:7749)
at com.android.server.wm.WindowManagerService.setEventDispatching(WindowManagerService.java:7628)
at com.android.server.am.ActivityManagerService.updateEventDispatchingLocked(ActivityManagerService.java:8083)
at com.android.server.am.ActivityManagerService.wakingUp(ActivityManagerService.java:8077)
at com.android.server.power.Notifier.sendWakeUpBroadcast(Notifier.java:474)
at com.android.server.power.Notifier.sendNextBroadcast(Notifier.java:455)
at com.android.server.power.Notifier.access$700(Notifier.java:62)
at com.android.server.power.Notifier$NotifierHandler.handleMessage(Notifier.java:600)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:194)
at com.android.server.ServerThread.run(SystemServer.java:1328)
從trace文件看,是因為TID為24的線程等待一個TID為12的線程持有的鎖,TID為12的線程等待一個TID為85的線程持有的鎖,而TID為85的線程確等待一個TID為24的線程持有的鎖,導致了循環等待的現象,對應的trace文件的語句如下:
TID 24:- waiting to lock <0x41a874a0> (a com.android.server.am.ActivityManagerService) held by tid=12 (android.server.ServerThread)
TID 12: - waiting to lock <0x41a7e2e8> (a java.lang.Object) held by tid=85 (Binder_B)
TID 85:- waiting to lock <0x41a7e420> (a com.android.server.power.PowerManagerService$DisplayBlankerImpl) held by tid=24 (PowerManagerService)
既然是死鎖,那么先看各線程都有那些鎖。
先看TID=24的線程的棧頂,ActivityManagerService的broadcastIntent函數代碼如下:
復制代碼 代碼如下:

public final int broadcastIntent(IApplicationThread caller,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle map,
String requiredPermission, boolean serialized, boolean sticky, int userId) {
enforceNotIsolatedCaller("broadcastIntent");
synchronized(this) {
intent = verifyBroadcastLocked(intent);
final ProcessRecord callerApp = getRecordForAppLocked(caller);
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
int res = broadcastIntentLocked(callerApp,
callerApp != null ? callerApp.info.packageName : null,
intent, resolvedType, resultTo,
resultCode, resultData, map, requiredPermission, serialized, sticky,
callingPid, callingUid, userId);
Binder.restoreCallingIdentity(origId);
return res;
}

可以看到TID=24需要ActivityManagerService這個鎖。再看TID=12線程的棧頂,PowerManagerService的isScreenOnInternal函數代碼如下:
復制代碼 代碼如下:

private boolean isScreenOnInternal() {
synchronized (mLock) {
return !mSystemReady
|| mDisplayPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF;
}
}

可以看到需要PowerManagerService的mlock這個鎖。最后看TID=85線程的棧頂,同樣在PowerManagerService里面,內部類DisplayBlankerImpl的toString函數:
復制代碼 代碼如下:

public String toString() {
synchronized (this) {
return "blanked=" + mBlanked;
}
}

這是在內部類DisplayBlankerImpl里面實現的,所以需要DisplayBlankerImpl這個鎖。
對應的表格如下:
 
表一 各線程等待的鎖情況
從表一來看,沒有出現死鎖現象,似乎并不是我們所想的那樣。難道不是死鎖?開始有點小懷疑自己了,難道別的原因導致的。也許只看調用堆棧的頂端可能不行,棧頂只能看出各線程需要的鎖,不能僅看自己要什么吧!一味索取可不好!人不是這樣做的!看一下整個的堆棧調用流程,看看自己擁有了那些鎖。
跟蹤TID=24線程的堆棧,在PowerManagerService內部類DisplayBlankerImpl的unblankAllDisplays函數中持有鎖:
復制代碼 代碼如下:

public void unblankAllDisplays() {
synchronized (this) {
nativeSetAutoSuspend(false);
nativeSetInteractive(true);
mDisplayManagerService.unblankAllDisplaysFromPowerManager();
mBlanked = false;
///M: add for tvout and hdmi
mTvOut.tvoutPowerEnable(true);
mHDMI.hdmiPowerEnable(true);
///@}
if (DEBUG) {
Slog.d(TAG_P, "unblankAllDisplays out ...");
}
if (mBootCompleted) {
Intent intent = new Intent(ACTION_LOCK_SCREEN_SHOW);
mContext.sendBroadcast(intent);
}
}
}

最后發送廣播的代碼,是我們自己添加的。根據unblankAllDisplays函數和broadcastIntent函數,可以看到TID=24的線程此時持有了DisplayBlankerImpl鎖(unblankAllDisplays),等待ActivityManagerService鎖(broadcastIntent)釋放。
同樣,跟蹤TID=12線程的堆棧,在ActivityManagerService的wake_up函數中持有鎖:
復制代碼 代碼如下:

public void wakingUp() {
if (checkCallingPermission(android.Manifest.permission.DEVICE_POWER)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires permission "
+ android.Manifest.permission.DEVICE_POWER);
}
synchronized(this) {
Slog.i(TAG, "wakingUp");
mWentToSleep = false;
updateEventDispatchingLocked();
comeOutOfSleepIfNeededLocked();
}
}

根據wakingUp函數和isScreenOnInternal函數,可以看到TID=12的線程持有ActivityManagerService鎖(wakingUp),等待PowerManagerService.mLock鎖(isScreenOnInternal)。到這,似乎看到了希望,迷霧要撥開了,有點小自信是死鎖導致的,但還不能最終下結論。
一鼓作氣,跟蹤TID=85線程的堆棧,在PowerManagerService的dump有持有鎖的操作:
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
....
synchronized (mLock) {
...
}
根據toString函數和dump函數,可以看到TID=85線程此時持有PowerManagerService.mLock鎖(dump),需要DisplayBlankerImpl(toString)。
似乎謎底已經揭曉了,如果你還沒有看出來(其實我也沒看出來),來個表看看吧!
 
表二 各線程鎖的情況
清楚了嗎?多么清晰的循環等待呀!死鎖都死的這么完美,還是圖表效果好,看來有時候在紙上畫畫還是有用的!
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
成人久久18免费网站图片| 成人动漫网站在线观看| 国产女同一区二区| 亚洲第一精品夜夜躁人人躁| 88xx成人精品| 欧美精品在线第一页| 国产精品久久久久久久久久小说| 国产精品综合久久久| 九九视频这里只有精品| 欧美刺激性大交免费视频| 国产亚洲精品va在线观看| 91香蕉国产在线观看| 欧美国产亚洲精品久久久8v| 伊人男人综合视频网| 亚洲人午夜精品免费| 欧美日韩美女在线| 欧美日韩亚洲一区二| 自拍亚洲一区欧美另类| 中文字幕自拍vr一区二区三区| 91免费国产网站| 国产精品扒开腿做爽爽爽的视频| 庆余年2免费日韩剧观看大牛| 欧美野外猛男的大粗鳮| 亚洲性无码av在线| 色综合久久中文字幕综合网小说| 亚洲va男人天堂| 亚洲成av人片在线观看香蕉| 久久香蕉精品香蕉| 欧美激情精品久久久久久黑人| 亚洲乱码国产乱码精品精| 国产成人精品免高潮费视频| 日韩av在线免费观看一区| 欧美午夜片欧美片在线观看| 亚洲精品电影在线| 91精品国产免费久久久久久| 久久久免费电影| 日韩av成人在线| 亚洲精品在线观看www| 奇米一区二区三区四区久久| 亚洲一区二区久久久久久| 国产视频久久网| 91精品国产综合久久香蕉最新版| 日韩精品免费在线视频| 日韩电影中文字幕在线观看| 国产亚洲免费的视频看| 欧美午夜美女看片| 亚洲综合日韩在线| 成人免费大片黄在线播放| 日韩激情av在线免费观看| 欧美日韩在线看| 高跟丝袜一区二区三区| 日韩有码在线播放| 久久99久国产精品黄毛片入口| 成人激情视频在线播放| 欧美国产日韩在线| 欧美极品少妇xxxxx| 亚洲午夜小视频| 欧美高清无遮挡| 国产精品丝袜久久久久久不卡| 亚洲国产天堂久久综合网| 中国日韩欧美久久久久久久久| 亚洲一区二区在线播放| 亚洲欧美色图片| 国产日韩中文在线| 欧美成人午夜激情视频| 久久久久亚洲精品成人网小说| 日本一区二区在线免费播放| 福利微拍一区二区| 国产精品久久久久久久7电影| 日韩在线视频免费观看高清中文| 1769国内精品视频在线播放| 国产福利精品视频| 国产视频综合在线| 国产一区二区三区日韩欧美| 成人在线小视频| 青青草精品毛片| 国内精品小视频在线观看| 日韩欧美国产骚| 国产一区二区欧美日韩| 国产精品爱啪在线线免费观看| 97欧美精品一区二区三区| 欧美放荡办公室videos4k| 亚洲国产91色在线| 亚洲第一精品久久忘忧草社区| 青草青草久热精品视频在线观看| 国产成人精彩在线视频九色| 在线观看亚洲区| 国产精品免费一区二区三区都可以| 色99之美女主播在线视频| 成人午夜激情网| 精品国产网站地址| 欧美孕妇与黑人孕交| 国产色婷婷国产综合在线理论片a| 一本色道久久综合狠狠躁篇怎么玩| 美女999久久久精品视频| 国产欧美久久久久久| 成人久久18免费网站图片| 国产日本欧美一区二区三区| 久久久精品久久久| 国产午夜精品麻豆| 欧美激情精品久久久久久免费印度| 欧美一区第一页| 国产成人福利夜色影视| 国产精品视频网址| 国产精品美女在线| 欧美性xxxx极品hd欧美风情| 久久91亚洲精品中文字幕奶水| 91精品国产99| 亚洲香蕉av在线一区二区三区| 亚洲第一网中文字幕| 国产成人亚洲精品| 在线看片第一页欧美| 国产精品中文字幕在线| 国产精品极品在线| 国产精品69久久久久| 久久大大胆人体| 久久乐国产精品| 亚洲男人天堂古典| 日韩高清电影免费观看完整版| 亚洲男人天堂网站| 98精品国产自产在线观看| 亚洲精品国产suv| 亚洲经典中文字幕| 国产精品美女免费看| 久久久噜噜噜久久中文字免| 欧美综合国产精品久久丁香| 久久乐国产精品| 日本久久久a级免费| 91中文字幕在线观看| 欧美成人免费大片| 久热精品在线视频| 日韩精品在线免费播放| 热久久美女精品天天吊色| 亚洲色图在线观看| 好吊成人免视频| 日韩在线欧美在线国产在线| 国产精品久久久久久中文字| 国产精品高清网站| 欧美日本国产在线| 久久久在线免费观看| 免费av一区二区| 亚洲成人教育av| 中文字幕精品网| 这里只有精品视频| 成人激情免费在线| 亚洲天堂男人的天堂| 亚洲网站在线播放| 精品久久久国产精品999| 国语自产精品视频在免费| 欧美日韩国产一区在线| 国产中文字幕91| 亚洲欧美一区二区三区四区| 亚洲欧美日韩一区在线| zzijzzij亚洲日本成熟少妇| 91久久综合亚洲鲁鲁五月天| 一区二区三区日韩在线| 91色琪琪电影亚洲精品久久| 欧美日韩美女在线观看| 日韩一区二区三区在线播放| 欧美激情2020午夜免费观看| 视频在线观看一区二区| 日韩免费观看网站| 色偷偷噜噜噜亚洲男人| 国产噜噜噜噜久久久久久久久|