免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3455 | 回复: 3
打印 上一主题 下一主题

OPhone应用程序内存泄漏确认与定位 [复制链接]

论坛徽章:
59
2015七夕节徽章
日期:2015-08-24 11:17:25ChinaUnix专家徽章
日期:2015-07-20 09:19:30每周论坛发贴之星
日期:2015-07-20 09:19:42ChinaUnix元老
日期:2015-07-20 11:04:38荣誉版主
日期:2015-07-20 11:05:19巳蛇
日期:2015-07-20 11:05:26CU十二周年纪念徽章
日期:2015-07-20 11:05:27IT运维版块每日发帖之星
日期:2015-07-20 11:05:34操作系统版块每日发帖之星
日期:2015-07-20 11:05:36程序设计版块每日发帖之星
日期:2015-07-20 11:05:40数据库技术版块每日发帖之星
日期:2015-07-20 11:05:432015年辞旧岁徽章
日期:2015-07-20 11:05:44
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-09-03 14:37 |只看该作者 |倒序浏览
本帖最后由 renxiao2003 于 2010-09-03 14:40 编辑

OPhone应用程序内存泄漏确认与定位OPhone平台开发, 2010-07-26 16:23:34 标签 :
1、如何确定内存泄露。

突然有一天tester对我们说com.android.browser在反复启动/退出时有内存泄露。那我们首先需要重现一下。
    OPhone 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                                             
$                                                                       


对于procrank我们主要参考Uss列,dumpsys info我们看priv dirty。

如果没有自动化测试工具,那只能手工重现这个问题。让我们做这个动作启动/退出浏览器50次。 做这之前我们来写一个脚本testleak.sh,记录这个过程browser内存的变化。这里我们仅仅用procrank观察,这已经足够了。
testleak.sh                                                            

#!/system/bin/sh                                                        


while true; do                                                         
date >> ./procrank.log                                                  
procrank >> ./procrank.log                                             
echo >> ./procrank.log                                                  


sleep 5                                                                 
done                                                                    


这个脚本的用途是每5秒钟让系统输出一次procrank的结果到procrank.log里面。把这个脚本push到手机的某个目录下,执行:

# ./testleak.sh &                                                      


重复测试步骤若干次,借助excel,我们可以从procrank.log把browser相关的结果找出来,假设是这样的。

PID       Vss     Rss     Pss    Uss   cmdline                        
...                                                                     
2537    29048K 29048K 12735K 8628K   com.android.browser            
2537    29168K 29168K 12854K 8748K   com.android.browser            
2537    29088K 29088K 12775K 8668K   com.android.browser            
2537    29488K 29488K 13177K 9072K   com.android.browser            
2537    29348K 29348K 13037K 8932K   com.android.browser            
2537    29540K 29540K 13229K 9124K   com.android.browser            
2537    29564K 29564K 13253K 9148K   com.android.browser            
2537    29460K 29460K 13149K 9044K   com.android.browser            
2537    29460K 29460K 13149K 9044K   com.android.browser            
2537    29484K 29484K 13173K 9068K   com.android.browser            
...                                                                     

我们做一张图,如下(图1)


1 Uss变化曲线图



很明显内存在反复中稳定上升。如果内存在一段时间后没有下降,我们可以认为它是leak的。这里需要补充一下,有些内存的泄漏是微量的,可能需要做几百遍才能看到曲线的增长,另外测试机的使用时间也影响测试结果,一般来说,用过一段时间的手机上的测试结果更明显。

2、定位泄漏的位置。

这里分两种情况,一种是纯java的泄露,另外一种是底层(C/C++)的泄漏。如果通过代码走查的方式查找的效果不好,就需要一些辅助工具了。

首先我们需要一个工具是mat,它是免费的,可以直接使用RCP版本或者安装其eclipse的插件,下载地址是http://www.eclipse.org/mat/downloads.php 。用它分析hprof文件,可以看出哪些object没有被释放。

让我们先获得一个hprof文件,这个文件存放某个process当前内存使用的一个快照。

# chmod 777 /data/misc                                                  
# kill -10 2537                                                         


这样会在/data/misc目录下生成一个带当前时间的hprof文件,比如
heap-dump-tm1275041385-pid2537.hprof

然后我们需要借助OPhone SDK提供的工具hprof-conv 来把上面的hprof转化为mat可以读取的格式。

$ adb pull /data/misc/heap-dump-tm1275041385-pid2537.hprof desktop/                  
...SDK/tools# hprof-conv /data/misc/heap-dump-tm1275041385-pid2537.hprof pid2537.hprof                                                           


用mat或eclipse打开(如果装mat插件的话),选择[Leak Suspects Report],如图2 :

图2


选择[Open Dominator Tree for entire heap]
   


图3

选择[Group result by...],下拉列表中勾选[Group result by class loader],如图4:

图4


我们主要看Objects这一列。如图5:
   

图5


因为hprof保存的是内存快照,我们可以在程序启动前获得一个hprof文件,在做完50次的测试后再获得一个文件,两者对比,如果出现object的数量与次数一起递增,那么相对应的class就是泄漏的对象了,参照代码,很容易我们就能找到泄漏的地方。但是如果无论执行多少遍,objects的数量都没有变化,这样就不得不考虑是不是native的问题了。

这种情况得特别对待,最直白的定位方法就是试,把认为内存泄漏的地方给注释掉,重新打包再测。其实如果有相当大把握的怀疑,这种方法是最有效的。但是很多次后还没有确定泄漏的范围就尝试其他方法吧。
    OPhone SDK提供了一些获得内存信息的api,使用如下:

ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
MemoryInfo info = new MemoryInfo();                                                     
activityManager.getMemoryInfo(info);                                                   
Log.i("memory free:", "" + info.availMem);                                             


在测试步骤涉及的相关代码中加上这些log,可以得出一系列内存变化的情况,这样也可以看出来是在哪里出现的问题。
解决泄漏不在本文讨论范围。


附录:
·
VSS - Virtual Set Size 虚拟耗用内存(包含共享库占用的内存)
·
RSS - Resident Set Size 实际使用物理内存(包含共享库占用的内存)
·
PSS - Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存)

USS - Unique Set Size 进程独自占用的物理内存(不包含共享库占用的内存)

评分

参与人数 2可用积分 +60 收起 理由
prolj + 30 hao
T-Bagwell + 30 精品文章

查看全部评分

论坛徽章:
59
2015七夕节徽章
日期:2015-08-24 11:17:25ChinaUnix专家徽章
日期:2015-07-20 09:19:30每周论坛发贴之星
日期:2015-07-20 09:19:42ChinaUnix元老
日期:2015-07-20 11:04:38荣誉版主
日期:2015-07-20 11:05:19巳蛇
日期:2015-07-20 11:05:26CU十二周年纪念徽章
日期:2015-07-20 11:05:27IT运维版块每日发帖之星
日期:2015-07-20 11:05:34操作系统版块每日发帖之星
日期:2015-07-20 11:05:36程序设计版块每日发帖之星
日期:2015-07-20 11:05:40数据库技术版块每日发帖之星
日期:2015-07-20 11:05:432015年辞旧岁徽章
日期:2015-07-20 11:05:44
2 [报告]
发表于 2010-09-03 14:38 |只看该作者
也适用于Android系统啊。

论坛徽章:
59
2015七夕节徽章
日期:2015-08-24 11:17:25ChinaUnix专家徽章
日期:2015-07-20 09:19:30每周论坛发贴之星
日期:2015-07-20 09:19:42ChinaUnix元老
日期:2015-07-20 11:04:38荣誉版主
日期:2015-07-20 11:05:19巳蛇
日期:2015-07-20 11:05:26CU十二周年纪念徽章
日期:2015-07-20 11:05:27IT运维版块每日发帖之星
日期:2015-07-20 11:05:34操作系统版块每日发帖之星
日期:2015-07-20 11:05:36程序设计版块每日发帖之星
日期:2015-07-20 11:05:40数据库技术版块每日发帖之星
日期:2015-07-20 11:05:432015年辞旧岁徽章
日期:2015-07-20 11:05:44
3 [报告]
发表于 2010-09-03 16:09 |只看该作者
申请精华(转自ophonesdn),所以不敢说是原创。

论坛徽章:
59
2015七夕节徽章
日期:2015-08-24 11:17:25ChinaUnix专家徽章
日期:2015-07-20 09:19:30每周论坛发贴之星
日期:2015-07-20 09:19:42ChinaUnix元老
日期:2015-07-20 11:04:38荣誉版主
日期:2015-07-20 11:05:19巳蛇
日期:2015-07-20 11:05:26CU十二周年纪念徽章
日期:2015-07-20 11:05:27IT运维版块每日发帖之星
日期:2015-07-20 11:05:34操作系统版块每日发帖之星
日期:2015-07-20 11:05:36程序设计版块每日发帖之星
日期:2015-07-20 11:05:40数据库技术版块每日发帖之星
日期:2015-07-20 11:05:432015年辞旧岁徽章
日期:2015-07-20 11:05:44
4 [报告]
发表于 2010-09-04 13:27 |只看该作者
学收藏先… 前两天qa那边的变态竟然查出了大约为200k的内存泄露…很崩溃…
Kallawa 发表于 2010-09-03 21:49



    查出来了还不错。我们经常是报了outofmemoryerr后再去找原因的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP