句柄泄漏和Handler的底層機(jī)制

【簡介】

???之前在做一個無埋點(diǎn)SDK相關(guān)開發(fā)的時候戳气,由于上報邏輯比較復(fù)雜蛛壳,故而想到了用hander隊(duì)列的形式處理事件的上報,但是SDK上線之后齐邦,發(fā)現(xiàn)出了一個句柄泄漏的bug,百思不得其解第租,后來看了Handler的底層源碼措拇,又做了一些句柄數(shù)的追蹤和分析,解決了這個問題慎宾。

????一丐吓、Handler在java層的機(jī)制

????如下圖浅悉,handler的應(yīng)用層機(jī)制很簡單,不同的線程通過handler券犁,發(fā)送message到messageQueue里面术健,對應(yīng)的Looper開啟一個死循環(huán),然后一直輪詢粘衬,如果隊(duì)列里有待處理的消息荞估,就處理消息;如果沒有消息稚新,則開始休眠勘伺,節(jié)約資源。個中細(xì)節(jié)就不在贅述褂删,如有需要飞醉,可以自行搜索相關(guān)資料。

Handler的應(yīng)用層機(jī)制


????二屯阀、Handler的native層機(jī)制

????我們首先來看Looper.loop()的源碼

Looper.loop()源碼

????我們發(fā)現(xiàn)缅帘,在這個死循環(huán)里,它調(diào)用了MessageQueue下的next方法难衰,那么我們再看看這個next方法干了些什么:

MessageQueue的next()方法

????關(guān)鍵方法是這個nativePollOnce():當(dāng)運(yùn)行到這里時钦无,會調(diào)用native層的方法,系統(tǒng)去輪詢一次盖袭,如果MessageQueue當(dāng)前沒有要處理的Message铃诬,則線程休眠,不占用資源苍凛,這里為什么休眠不會產(chǎn)生ANR呢趣席,我們后面會分析。

? ? 我們現(xiàn)在注意一下nextPollTimeoutMillis這個變量醇蝴,這個變量代表MessageQueue下次被喚醒的時間宣肚。我們知道,MessageQueue里Message在加入隊(duì)列的時候悠栓,會按照執(zhí)行的時間順序排列霉涨;每次消息入隊(duì)列時,MessageQueue都會盡量計(jì)算出一個精確的時間惭适,假如這個時間是計(jì)算出來是2000ms笙瑟,此時消息隊(duì)列中沒有消息需要馬上處理時,會判斷用戶是否設(shè)置了Idle Handler癞志,如果有的話往枷,則會嘗試處理mIdleHandlers中所記錄的所有Idle Handler,此時會逐個調(diào)用這些Idle Handler的queueIdle()成員函數(shù),只會會再次調(diào)用nativePollOnce()方法错洁,線程阻塞住秉宿,不占用資源。當(dāng)時間到了屯碴,會往管道流中寫入字節(jié)流描睦,喚醒線程,處理Message导而。

? ? 我們知道忱叭,安卓的底層是Linux系統(tǒng)。當(dāng)Looper休眠時今艺,用的是底層的epoll機(jī)制來完成阻塞動作韵丑,故而不會產(chǎn)生ANR。

? ? 源碼的喚醒調(diào)用如圖:

MessageQueue.cpp的nativeWake()

? ? 最終調(diào)用了Looper.cpp源碼的wake()方法

Lopper.cpp的wake()方法

? ? 我們可以看到洼滚,喚醒只是往管道流里寫了一個"w"的字符流。所以喚醒機(jī)制技潘,我們可以直觀的理解為:

喚醒機(jī)制

? ? 在Linux底層遥巴,每個線程所能操作的句柄上限是1024個,一旦超過了這個值享幽,則會報句柄泄漏的錯誤铲掐,導(dǎo)致崩潰。

? ? 所以值桩,是不是我們的上報無埋點(diǎn)的數(shù)據(jù)時摆霉,頻繁的休眠喚醒導(dǎo)致句柄數(shù)超過了上限呢?


????三奔坟、查看線程的句柄數(shù)

? ? 我們需要一個root了的手機(jī)携栋,如果手頭沒有能用的測試機(jī),可以使用模擬器咳秉。

? ? 我用了一個低版本的模擬器(5.0版本)婉支,因?yàn)楦甙姹镜哪M器也不好直接獲取root。

? ? 我們先要獲取進(jìn)程的id澜建,這個可以通過AS的Logcat查看向挖。

? ? 之后通過adb shell進(jìn)入模擬器,cd到/proc/進(jìn)程id/fd文件夾下炕舵,然后ls -al何之,就可以在Logcat中打印出當(dāng)前線程所消耗的句柄。如果你沒有root權(quán)限咽筋,fd文件夾是訪問不了的溶推。

????筆者在啟動APP后,正常使用了一下APP,接著打印出了當(dāng)前程序占用的句柄數(shù)悼潭,發(fā)現(xiàn)有800多個句柄開銷庇忌,大多數(shù)是數(shù)據(jù)庫所持有的,搞了半天原來是數(shù)據(jù)庫的問題舰褪。但是為了防止意外皆疹,筆者已經(jīng)把SDK中的所有Handler替換掉了。


? ? 四占拍、總結(jié)

? ? 在android開發(fā)中略就,我們的這些操作會消耗句柄數(shù):

? ? 1.數(shù)據(jù)庫的讀寫,不關(guān)及時關(guān)流會導(dǎo)致句柄開銷增大晃酒;

? ? 2.文件流的讀寫表牢,如果操作不好,也容易導(dǎo)致句柄消耗過大贝次;

? ? 3.Handler頻繁喚醒等崔兴。

? ? 一旦出現(xiàn)句柄泄漏的問題,核心思想就去排查流的讀寫有沒有出問題蛔翅。因?yàn)樵诎沧康讓忧们眩琇inux對于句柄的操作很多都是通過流來體現(xiàn)的,如果句柄數(shù)超過了上限山析,肯定會出問題堰燎。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市笋轨,隨后出現(xiàn)的幾起案子秆剪,更是在濱河造成了極大的恐慌,老刑警劉巖爵政,帶你破解...
    沈念sama閱讀 221,888評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件仅讽,死亡現(xiàn)場離奇詭異,居然都是意外死亡钾挟,警方通過查閱死者的電腦和手機(jī)何什,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來等龙,“玉大人处渣,你說我怎么就攤上這事≈肱椋” “怎么了罐栈?”我有些...
    開封第一講書人閱讀 168,386評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長泥畅。 經(jīng)常有香客問我荠诬,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,726評論 1 297
  • 正文 為了忘掉前任柑贞,我火速辦了婚禮方椎,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘钧嘶。我一直安慰自己棠众,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,729評論 6 397
  • 文/花漫 我一把揭開白布有决。 她就那樣靜靜地躺著闸拿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪书幕。 梳的紋絲不亂的頭發(fā)上新荤,一...
    開封第一講書人閱讀 52,337評論 1 310
  • 那天,我揣著相機(jī)與錄音台汇,去河邊找鬼苛骨。 笑死,一個胖子當(dāng)著我的面吹牛苟呐,可吹牛的內(nèi)容都是我干的痒芝。 我是一名探鬼主播,決...
    沈念sama閱讀 40,902評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼掠抬,長吁一口氣:“原來是場噩夢啊……” “哼吼野!你這毒婦竟也來了校哎?” 一聲冷哼從身側(cè)響起两波,我...
    開封第一講書人閱讀 39,807評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎闷哆,沒想到半個月后腰奋,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,349評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡抱怔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,439評論 3 340
  • 正文 我和宋清朗相戀三年劣坊,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片屈留。...
    茶點(diǎn)故事閱讀 40,567評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡局冰,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出灌危,到底是詐尸還是另有隱情康二,我是刑警寧澤,帶...
    沈念sama閱讀 36,242評論 5 350
  • 正文 年R本政府宣布勇蝙,位于F島的核電站沫勿,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜产雹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,933評論 3 334
  • 文/蒙蒙 一诫惭、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蔓挖,春花似錦夕土、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至荒适,卻和暖如春梨熙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背刀诬。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評論 1 272
  • 我被黑心中介騙來泰國打工咽扇, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人陕壹。 一個月前我還...
    沈念sama閱讀 48,995評論 3 377
  • 正文 我出身青樓质欲,卻偏偏與公主長得像,于是被迫代替她去往敵國和親糠馆。 傳聞我的和親對象是個殘疾皇子嘶伟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,585評論 2 359

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