Android開發(fā)中難免碰到ANR問題,但是網(wǎng)上關于ANR的文章并不多,那我就寫一篇最近工作中碰到ANR的分析過程。
分析過程
- 先查一下網(wǎng)上關于ANR方面的文章,找到的大部分都是說不要主線程執(zhí)行耗時操作,但是我本來就在子線程里執(zhí)行的下載操作的。怎么會產(chǎn)生ANR?
- 接著去分析 /data/anr/traces.txt, 好家伙data文件夾不是要root權限 才能訪問嗎?怎么辦不是要我root吧,然后我又去查了資料發(fā)現(xiàn)可以用下面的命令導出traces文件
adb shell cat /data/anr/traces.txt > e:\anr.txt
- 打開anr.txt 有1000多行看著都暈,沒辦法慢慢看吧,看到SharedPreferences想到了我不是在下載的時候存了下載的進度了,猜想應該是它出的問題
| group="main" sCount=1 dsCount=0 obj=0x12dbdac0 self=0xb4256800
| sysTid=4302 nice=0 cgrp=default sched=0/0 handle=0x9d207000
| state=S schedstat=( 11836166912 2318327808 16610 ) utm=552 stm=631 core=1 HZ=100
| stack=0x9c7f2000-0x9c7f4000 stackSize=1036KB
| held mutexes=
at libcore.io.Posix.fsync(Native method)
at libcore.io.BlockGuardOs.fsync(BlockGuardOs.java:143)
at java.io.FileDescriptor.sync(FileDescriptor.java:74)
at android.os.FileUtils.sync(FileUtils.java:152)
at android.app.SharedPreferencesImpl.writeToFile(SharedPreferencesImpl.java:598)
at android.app.SharedPreferencesImpl.access$800(SharedPreferencesImpl.java:51)
at android.app.SharedPreferencesImpl$2.run(SharedPreferencesImpl.java:512)
- locked <@addr=0x131d6bf0> (a java.lang.Object)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
然后去代碼里查了一下寫的apply 方法,再去網(wǎng)上查了一下apply、和commit的區(qū)別
SharedPreferencesImpl源碼分析
原來的apply方法是異步執(zhí)行的,因為下載很快 有進行一次寫入操作,在異步寫入時導致死鎖。
commit是同步的阻塞的。那就把apply改成commit試一下,果然ok了。
TIP
在分析traces.txt首先搜索自己項目包名的堆棧,這樣能很快定位問題,如果沒有那就要一步一步的看,在關聯(lián)自己的代碼進行聯(lián)想。應該能解決ANR問題。