Android应用中经常遇到的问题就是内存溢出。因此,该问题需要投入更多的精力!
Android 的SDK提供了两种命令procrank和dumpsys meminfo [pid] 来查看当前内存的使用情况
$procrank
PID Vss Rss Pss Uss cmdline
935 68544K 42160K 19570K 15840K system_server
1002 37600K 35124K 14912K 12804K oms.home
1221 33828K 33828K 12259K 9440K com.android.phone
2537 31916K 31916K 11510K 9324K com.android.Browser
2956 28768K 28768K 9034K 7152K com.hiapk.market
...
854 268K 268K 89K 84K /system/bin/servicemanager
859 444K 444K 86K 28K /system/bin/sdm
920 268K 268K 85K 80K /system/bin/cbmon
883 404K 404K 84K 28K /system/bin/sdm
857 276K 276K 81K 76K /system/bin/debuggerd
$ dumpsys meminfo 2537
Currently running services:
meminfo
-----------------------------------------------------------------
DUMP OF SERVICE meminfo:
Applications Memory Usage (kB):
Uptime: 12697585 Realtime: 49787601
** MEMINFO in pid 2537 [com.android.browser] **
native dalvik other total
size: 6432 4295 N/A 10727
allocated: 5823 3142 N/A 8965
free: 4 1153 N/A 1157
(Pss): 3396 1858 6166 11420
(shared dirty): 1260 4872 692 6824
(priv dirty): 3332 1612 1608 6552
Objects
Views: 50 ViewRoots: 1
AppContexts: 2 Activities: 1
Assets: 3 AssetManagers: 3
Local Binders: 14 Proxy Binders: 73
Death Recipients: 2
OpenSSL Sockets: 0
SQL
heap: 275 dbFiles: 0
numPagers: 4 inactivePageKB: 82
activePageKB: 0
$
可以写一个shell脚本收集系统状态信息:leak.sh
#!/system/bin/sh
while true; do
data >> ./procrank.log
procrank >> ./procrank.log
echo >> ./procrank.log
sleep 5
done
然后运行该脚本,收集系统信息后,根据收集到的系统信息判断是否可能存在内存溢出的问题。
(注:主要是查看 Uss列数据是否是处于增长状态)
如果是,则存在内存溢出的问题,这就需要我们对可能发生的溢出点进行定位。之后与网站的相同,借助Eclipse的一个插件mat,进行分析
首先获得占用内存最大的进程的快照,我们可以通过获得hprof文件实现。
如下:
$chmod 777 /data/misc
$kill -10 [pid]
这样将在/data/misc目录下生成一个带当前时间的hprof文件,比如
heap-dump-tm1275041385-pid2537.hprof
然后通过sdk提供的工具hprof-conv将hprof转换为mat可以读取的格式
$adb pull /data/mic/hprof文件 desktop/
$...sdk/tools$ hprof-conv /data/misc/hprof文件 pidA.hprof
只有用mat打开进行分析。为了更准确定位,需要多次生成快照进行对比,还是可以学习到很多知识!
同时,SDK还提供了获得内存信息的api,详情如下:
ActivityManager activityManager =(ActivityManager) getSystemService(ACTIVITY_SERVICE);
MemoryInfo info =new MemoryInfo();
activityManager.getMemoryInfo(info);