`
George_ghc
  • 浏览: 93816 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

应用程序内存泄漏确认与定位

阅读更多
【转:】http://dev.10086.cn/cmdn/wiki/index.php?edition-view-4521-1.html
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               
...                                     

  我们做一张图,如下



很明显内存在反复中稳定上升。如果内存在一段时间后没有下降,我们可以认为它是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],



选择[Open Dominator Tree for entire heap]



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



我们主要看Objects这一列。



因为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 进程独自占用的物理内存(不包含共享库占用的内存)

分享到:
评论

相关推荐

    使用 .Net Memory Profiler 诊断 .NET 应用内存泄漏(方法与实践)

    在.NET开发环境中,内存泄漏是一个严重的问题,可能导致应用程序性能下降,甚至崩溃。本文将深入探讨如何使用.Net Memory Profiler这一专业工具来诊断和解决.NET应用的内存泄漏问题。.Net Memory Profiler是一款强大...

    WebSphere应用服务器内存泄漏探测与诊断工具选择最佳实践

    ### WebSphere应用服务器内存泄漏探测与诊断工具选择最佳实践 #### 概述 WebSphere应用服务器作为企业级的中间件平台,承载着大量的业务逻辑和数据处理任务。然而,随着应用的复杂度增加,内存泄漏成为了一个不容...

    electron-vue开发环境内存泄漏问题汇总

    在使用Electron结合Vue进行桌面应用开发时,内存泄漏是一个常见且需要重点关注的问题。内存泄漏问题的出现会逐渐消耗系统资源,最终可能导致应用崩溃或运行缓慢。在Electron中,内存泄漏主要跟主进程和渲染进程的...

    WebSphere应用服务器内存泄漏探测与诊断工具.doc

    【WebSphere应用服务器内存泄漏探测与诊断工具】 内存泄漏是应用程序性能问题的常见表现,它会导致系统可用内存逐渐减少,最终引发内存不足(OutOfMemory)的严重情况,甚至导致系统崩溃。由于Java堆内存中对象及其...

    android应用内存泄露

    内存泄露的定义可以这样理解:当应用程序中的一些对象不再被使用,但由于某些原因仍然被系统所保留,即这些对象还被引用着,导致垃圾回收器无法正常回收它们,这就产生了内存泄露。 #### 二、检测方法 检测Android...

    内存释放工具能够有效释放应用程序内存资源

    5. **报告与日志**:内存释放工具通常还会提供详细的报告,列出释放内存的过程和结果,以便用户了解内存使用状况,帮助开发者定位和修复内存泄露问题。 "内存释放专家"这样的工具对于长时间运行的大型应用、服务器...

    应用服务器内存泄露问题诊断一例

    在这个案例中,通过分析内存回收图形,发现在Session过期后,内存有一次明显的下降,之后再次逐渐上升,进一步确认了内存泄漏与Session管理有关。因此,调整Session超时时间和优化Session中存储的数据成为了解决问题...

    利用JProfiler对应用服务器内存泄漏问题诊断.doc

    【JProfiler】是一款强大的Java应用程序性能分析工具,用于检测和诊断包括内存泄漏在内的各种性能问题。在本案例中,我们探讨了如何利用JProfiler来识别和解决应用服务器的内存泄漏问题,以提升系统的稳定性和性能。...

    此解决方案是ASP.NET mvc Web应用程序,它显示每次发出新的http请求时在内存中加载数组的内存泄漏.zip

    标题中的“此解决方案是ASP.NET MVC Web应用程序,它显示每次发出新的HTTP请求时在内存中加载数组的内存泄漏”揭示了一个关键问题,即在ASP.NET MVC应用中可能存在内存泄漏问题,尤其是在处理HTTP请求时。...

    最快速度找到内存泄漏

    当使用MFC编写的应用程序存在内存泄漏时,程序退出时会自动在调试窗口显示内存泄漏的相关信息。 - 示例代码展示了通过在`CMyApp::InitApplication()`函数中分配内存但未释放,从而引发内存泄漏的情况。 2. **非MFC...

    测试内存泄露测试软件

    4. **修复与验证**:修改代码以解决内存泄露问题,并重新运行测试以确认问题是否已解决。 5. **性能监控**:持续监控程序的内存使用情况,确保修复后的程序在长时间运行下内存使用保持稳定。 对于Web开发,除了...

    内存泄露与JProfiler

    内存泄露是程序运行过程中,无法释放不再使用的内存空间的现象,这会导致系统资源逐渐耗尽,影响应用程序的性能和稳定性。在Java这样的垃圾回收(GC)环境中,虽然大部分内存管理由虚拟机自动处理,但不当的编程习惯...

    Android内存泄漏调试教程

    1. 单例模式:不正确地使用单例类可能导致内存泄漏,因为它们的生命周期与应用程序相同。如果单例持有对某个Activity或其他短暂对象的引用,那么这些对象将不会被回收。 2. 静态变量:静态变量的生命周期贯穿整个...

    android手机测试中如何查看内存泄露

    - **排除弱引用**:右键点击某一项,选择Path to GC Roots -> exclude weak/soft references,进一步筛选出与程序相关的所有可能有内存泄露的类。 通过以上步骤,我们可以有效地检查和定位Android应用中的内存...

    内存泄漏检测工具leakcanry的资源

    内存泄漏在Android应用开发中是一个严重的问题,它会导致应用程序性能下降,甚至引发应用程序无响应(ANR)等问题。LeakCanary是一款强大的内存泄漏检测工具,由Square公司开发,专门为Android平台设计,帮助开发者...

    JProfiler内存泄漏查找文档

    - 分析内存泄漏时,需关注应用程序的运行状态,确保分析结果与实际运行情况相符。 - 定期进行内存剖析,形成监控习惯,以便及时发现并处理内存问题。 通过深入理解和熟练运用JProfiler,开发者可以有效地管理和...

    某应用内存溢出(暨jvm)分析分享

    标题 "某应用内存溢出(暨jvm)分析分享" 提到的是一个关于应用程序,特别是N银行消费信贷backend应用的内存溢出问题及其在Java虚拟机(JVM)层面上的分析。内存溢出是程序运行时由于分配的内存不足导致无法继续执行...

Global site tag (gtag.js) - Google Analytics