Android Watchdog學(xué)習(xí)筆記

Watchdog的作用是監(jiān)控系統(tǒng)服務(wù)有沒(méi)有卡住润歉,如果有模狭,就會(huì)重啟系統(tǒng)服務(wù)。

1. Watchdog的啟動(dòng)

SystemServer中創(chuàng)建Watchdog踩衩,并讓它的run跑起來(lái):

            final Watchdog watchdog = Watchdog.getInstance();
            watchdog.init(context, mActivityManagerService);
            ...
            Watchdog.getInstance().start();

2. 監(jiān)控服務(wù)

2.1 注冊(cè)監(jiān)控服務(wù)

系統(tǒng)服務(wù)首先會(huì)向Watchdog注冊(cè)自己

        Watchdog.getInstance().addMonitor(this);
        Watchdog.getInstance().addThread(mHandler);

注冊(cè)的內(nèi)容會(huì)放入Watchdog:

public void addMonitor(Monitor monitor) {
    // 將monitor對(duì)象添加到Monitor Checker中嚼鹉,
    // 在Watchdog初始化時(shí)贩汉,可以看到Monitor Checker本身也是一個(gè)HandlerChecker對(duì)象
    mMonitors.add(monitor);
}
 
public void addThread(Handler thread, long timeoutMillis) {
    synchronized (this) {
        if (isAlive()) {
            throw new RuntimeException("Threads can't be added once the Watchdog is running");
        }
        final String name = thread.getLooper().getThread().getName();
        // 為Handler構(gòu)建一個(gè)HandlerChecker對(duì)象,其實(shí)就是**Looper Checker**
        mHandlerCheckers.add(new HandlerChecker(thread, name, timeoutMillis));
    }

HandlerChecker會(huì)調(diào)用Monitor檢測(cè)服務(wù)狀態(tài)锚赤,同時(shí)根據(jù)檢測(cè)狀態(tài)做下一步處理匹舞。

2.2 Watchdog的監(jiān)控方式

Watchdog會(huì)在自己的run()方法中不斷進(jìn)行監(jiān)控:

    public void run() {

        while (true) {
            synchronized (this) {
                long timeout = CHECK_INTERVAL;
                // 1. 開(kāi)始監(jiān)控
                // Make sure we (re)spin the checkers that have become idle within
                // this wait-and-check interval
                for (int i=0; i<mHandlerCheckers.size(); i++) {
                    HandlerChecker hc = mHandlerCheckers.get(i);
                    hc.scheduleCheckLocked();
                }

            // 2. 給監(jiān)控線程一點(diǎn)時(shí)間(30s)
            long start = SystemClock.uptimeMillis();
            while (timeout > 0) {
                ...
                try {
                    wait(timeout);
                } catch (InterruptedException e) {
                    Log.wtf(TAG, e);
                }
                ...
                timeout = CHECK_INTERVAL - (SystemClock.uptimeMillis() - start);
            }
 
            // 3. 檢查HandlerChecker的完成狀態(tài)
            final int waitState = evaluateCheckerCompletionLocked();
            if (waitState == COMPLETED) {
                ...
                continue;
            } else if (waitState == WAITING) {
                ...
                continue;
            } else if (waitState == WAITED_HALF) {
                ...
                continue;
            }
 
            // 4. 存在超時(shí)的HandlerChecker
            blockedCheckers = getBlockedCheckersLocked();
            subject = describeCheckersLocked(blockedCheckers);
            allowRestart = mAllowRestart;
        }
        ...
        // 5. 保存日志,判斷是否需要?dú)⒌粝到y(tǒng)進(jìn)程
        Slog.w(TAG, "*** GOODBYE!");
        Process.killProcess(Process.myPid());

2.3 監(jiān)控服務(wù)時(shí)做了什么

HandlerChecker的scheduleCheckLocked用于發(fā)布一個(gè)HandlerChecker自己的run的執(zhí)行任務(wù):

       public void scheduleCheckLocked() {
            ...
            mStartTime = SystemClock.uptimeMillis();
            mHandler.postAtFrontOfQueue(this);
        }

執(zhí)行到被監(jiān)控的服務(wù)的monitor():

        public void run() {
            final int size = mMonitors.size();
            for (int i = 0 ; i < size ; i++) {
                synchronized (Watchdog.this) {
                    mCurrentMonitor = mMonitors.get(i);
                }
                mCurrentMonitor.monitor();
            }
            // 這里mCompleted置true线脚。如果死鎖或者等待超時(shí)沒(méi)來(lái)得及置true赐稽,會(huì)在檢測(cè)時(shí)被認(rèn)為服務(wù)出現(xiàn)了問(wèn)題
            synchronized (Watchdog.this) {
                mCompleted = true;
                mCurrentMonitor = null;
            }
        }

服務(wù)的monitor其實(shí)就是嘗試獲取一下鎖:

    public void monitor() {
        synchronized (this) { }
    }

為什么獲取鎖就可以監(jiān)控服務(wù)狀態(tài)?因?yàn)橄到y(tǒng)服務(wù)會(huì)被很多客戶端調(diào)用浑侥,需要處理多線程姊舵,就必然會(huì)用到鎖。如果出現(xiàn)死鎖寓落,或者某次調(diào)用卡住了占著鎖不放括丁,Watchdog就獲取不到鎖,就可以認(rèn)為服務(wù)出現(xiàn)了異常伶选。

2.3 檢查狀態(tài)

通過(guò)服務(wù)注冊(cè)的Handler(存在Watchdog的mHandlerCheckers中)史飞,來(lái)判斷服務(wù)的狀態(tài)。主要就是看Monitor方法是否順利完成仰税,若沒(méi)有完成就計(jì)算耗時(shí)情況构资。

    private int evaluateCheckerCompletionLocked() {
        int state = COMPLETED;
        for (int i=0; i<mHandlerCheckers.size(); i++) {
            HandlerChecker hc = mHandlerCheckers.get(i);
            state = Math.max(state, hc.getCompletionStateLocked());
        }
        return state;
    }

        public int getCompletionStateLocked() {
            if (mCompleted) {
                return COMPLETED;
            } else {
                long latency = SystemClock.uptimeMillis() - mStartTime;
                if (latency < mWaitMax/2) {
                    return WAITING;
                } else if (latency < mWaitMax) {
                    return WAITED_HALF;
                }
            }
            return OVERDUE;
        }

2.4 異常處理

出現(xiàn)異常有兩種處理:
1,殺異常的進(jìn)程

Watchdog: *** WATCHDOG KILLING SYSTEM PROCESS: XXX
Watchdog: XXX
Watchdog: "*** GOODBYE!

2肖卧,重啟

Rebooting system because:xxx
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蚯窥,一起剝皮案震驚了整個(gè)濱河市掸鹅,隨后出現(xiàn)的幾起案子塞帐,更是在濱河造成了極大的恐慌,老刑警劉巖巍沙,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件葵姥,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡句携,警方通過(guò)查閱死者的電腦和手機(jī)榔幸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)矮嫉,“玉大人削咆,你說(shuō)我怎么就攤上這事〈浪瘢” “怎么了拨齐?”我有些...
    開(kāi)封第一講書人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)昨寞。 經(jīng)常有香客問(wèn)我瞻惋,道長(zhǎng)厦滤,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任歼狼,我火速辦了婚禮掏导,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘羽峰。我一直安慰自己趟咆,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布限寞。 她就那樣靜靜地躺著忍啸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪履植。 梳的紋絲不亂的頭發(fā)上计雌,一...
    開(kāi)封第一講書人閱讀 51,718評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音玫霎,去河邊找鬼凿滤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛庶近,可吹牛的內(nèi)容都是我干的翁脆。 我是一名探鬼主播,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼鼻种,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼反番!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起叉钥,我...
    開(kāi)封第一講書人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤罢缸,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后投队,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體枫疆,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年敷鸦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了息楔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡扒披,死狀恐怖值依,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情碟案,我是刑警寧澤愿险,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站蟆淀,受9級(jí)特大地震影響拯啦,放射性物質(zhì)發(fā)生泄漏澡匪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一褒链、第九天 我趴在偏房一處隱蔽的房頂上張望唁情。 院中可真熱鬧,春花似錦甫匹、人聲如沸甸鸟。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)抢韭。三九已至,卻和暖如春恍箭,著一層夾襖步出監(jiān)牢的瞬間刻恭,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工扯夭, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鳍贾,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓交洗,卻偏偏與公主長(zhǎng)得像骑科,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子构拳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容