最近在处理项目的拷机问题,发现在测试24小时内,都是正常的,但是超过24小时后,重启一大片,让人抓狂。
分析了logcat打印,发现重启是因为系统服务已经被watchdog kill掉:
03-06 22:27:49.541 710 1064 W Watchdog: foreground thread stack trace:
03-06 22:27:49.542 710 1064 W Watchdog: at android.os.MessageQueue.nativePollOnce(Native Method)
03-06 22:27:49.542 710 1064 W Watchdog: at android.os.MessageQueue.next(MessageQueue.java:323)
03-06 22:27:49.542 710 1064 W Watchdog: at android.os.Looper.loop(Looper.java:135)
03-06 22:27:49.542 710 1064 W Watchdog: at android.os.HandlerThread.run(HandlerThread.java:61)
03-06 22:27:49.542 710 1064 W Watchdog: at com.android.server.ServiceThread.run(ServiceThread.java:46)
03-06 22:27:49.542 710 1064 W Watchdog: *** GOODBYE!
这种情况,就要抓anr的traces.txt来分析:
"AlarmManager" prio=5 tid=26 Runnable
| group="main" sCount=0 dsCount=0 obj=0x12ea03a0 self=0xeb2a6b00
| sysTid=755 nice=0 cgrp=default sched=0/0 handle=0xde222930
| state=R schedstat=( 98972491401001 276479663271 2197759 ) utm=9888269 stm=8980 core=1 HZ=100
| stack=0xde120000-0xde122000 stackSize=1038KB
| held mutexes= "mutator lock"(shared held)
.....
- locked <0x024448df> (a com.android.server.am.ActivityManagerService)
"main" prio=5 tid=1 Blocked
| group="main" sCount=1 dsCount=0 obj=0x3426dfa0 self=0xf3934500
| sysTid=710 nice=-2 cgrp=default sched=0/0 handle=0xf77344c0
| state=S schedstat=( 7312752856937 488253068832 1803739 ) utm=659213 stm=72062 core=1 HZ=100
| stack=0xff39d000-0xff39f000 stackSize=8MB
| held mutexes=
at com.android.server.am.ActivityManagerService.finishReceiver(ActivityManagerService.java:17259)
- waiting to lock <0x024448df> (a com.android.server.am.ActivityManagerService) held by thread 26
如上情况,main线程等待lock被tid=26的线程锁定的AcivitiyManagerService变量,一直无法获取到此对象,导致Watchdog超时,系统重启。
可是tid=26的线程状态是Runnable的,并没有等待其它锁,但为什么会造成持锁过久呢?
回到logcat的输出,没有发现明确的问题点。考虑到拷机要测试24小时后才会出现,有一种可能就是出现内在泄漏。这边采用eclipse的DDMS的插件进行分析。
下面是android sdk对这个工具的使用介绍:
Viewing heap usage for a process
DDMS allows you to view how much heap memory a process is using. This information is useful in tracking heap usage at a certain point of time during the execution of your application.
To view heap usage for a process:
- In the Devices tab, select the process that you want to see the heap information for.
- Click the Update Heap button to enable heap information for the process.
- In the Heap tab, click Cause GC to invoke garbage collection, which enables the collection of heap data. When the operation completes, you will see a group of object types and the memory that has been allocated for each type. You can click Cause GC again to refresh the data.
- Click on an object type in the list to see a bar graph that shows the number of objects allocated for a particular memory size in bytes.
下图是工具界面:
上面红框显示的#Objects是测试一段时间的数量,而开始前的数量如下:
可以看到#Objects出现了明显的增长。很可能出现了内存泄漏。因此,我们继续根据测试项运行的代码及系统调用,就可以比较容易定位到问题点。