美文网首页
内存泄漏分析(一)

内存泄漏分析(一)

作者: hookYuan | 来源:发表于2021-02-25 10:11 被阅读0次

    内存泄漏(memory leak),指程序在申请内存后,一直无法释放已申请的内存空间。内存泄露会消耗内存导致系统卡顿甚至崩溃(OOM),例如bitmap等大对象的泄漏相对容易发现,但对应一些小量的泄漏则容易被忽略,这时则需要运行自动化脚本,进行大量重复的操作才可能发现。

    1.内存泄漏概述()

    根据google的profiler对内存泄漏的分类,主要分为6类:Java层泄漏、Native层泄漏、Graphics泄漏、Stack泄漏、Code泄漏和其他泄漏。日常开发中主要分析的泄漏主要为前3种泄漏,对应各自的内存分配方案各自有对应的分析方法。在实际项目中面对测试提供的泄漏日志,首先要找到泄漏的点,较多内存泄漏可能发生在系统层(毕竟系统层代码量更多),找到了泄漏点后就可以霸气的回上一句:这不是我的问题,是XX的问题。

    2.java内存泄漏分析

    在Android中分析java层内存泄漏最常见的问题是Activity和Fragment的泄漏,关于java层内存泄漏主要有3种方式来分析:三方内存泄漏集成工具(如leakcanary)、profiler分析、MAT分析。

    1.三方内存泄漏集成工具常用的有:leakcanary等,可以在平时开发中自动上报内存泄漏适合开发时使用,集成简单,缺点是上报的信息只包含泄漏对象,无泄漏大小和引用次数等,使用步骤参考:https://github.com/square/leakcanary

    2.使用profiler分析。profiler为AndroidStudio自带的分析工具,可以分析手机实时内存信息和.hprof文件,例如使用内存分析时,打开profiler选择当前调试的应用程序,选择需要分析的进程,点击MEMORY,当发现内存大量增加并没有降低的时候,可以点击dump Java heap按钮开始记录,再次点击结束记录。此时会生成一个当前时间段的.hprof文件,当前可以查看如有Leaks选项表明存在Activity或Fragment的泄漏。对于其他的变量(常见的是我们的项目下变量)的泄漏可以观察是否存在增长并不销毁的情况,以此判断泄漏的地方。

    3.使用MAT分析。当拿到.hprof文件后使用MAT工具打开(如果是profiler生成的文件,需要进入 \Sdk\platform-tools目录,执行hprof-conv %pathFrom %pathTo进行转化后打开),这里我们主要关注的是Leak Suspects选项的内存占用情况,详细的使用方法参考https://blog.csdn.net/yincheng886337/article/details/50524890

    3.Native内存泄漏分析

    Native内存泄漏分析比较麻烦,由于hal层添加了camerahalserver来监控camera进程,我们可以预先调用adb shell dumpsys meminfo camerahalserver查看当前camera进程的使用情况,预先分析是否为Native内存泄漏。MTK Native内存泄漏分析(官方文档:https://online.mediatek.com/QuickStart/QS00086),使用以下方式分析,需将手机版本刷至userdebug或者eng版本并且开启mktlog后尝试:

    1.malloc内存泄漏分析步骤:
    a.打开android malloc debug机制并复现问题,

        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        a.对于Memory Corruption / Use After Free的case,可以设置成:
            setprop libc.debug.malloc.options "backtrace=16 guard=8 fill_on_free=16"
        b.对于Leakage的case,可以设置成:
            setprop libc.debug.malloc.options "backtrace=16 guard=8 fill_on_free=16 leak_track"
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        注:以上方式reboot后失效,因此对于userdebug可以通过以下设置:
        adb shell "echo libc.debug.malloc.options="backtrace=10 guard=8 fill_on_free=16 leak_track" >> /data/local.prop"
        adb shell "echo libc.debug.malloc.program= "app_process64" >> /data/local.prop"
        adb shell "chmod 644 /data/local.prop"
        
        打开coredump
        root
        shell setprop persist.aee.core.dump enable
        shell setprop persist.aee.core.direct enable
        reboot
    
        adb reboot
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        检查是否设置成功
        adb shell getprop | find "malloc"
    

    b.使用adb shell dumpsys meminfo camerahalserver查看当前camera进程的使用情况,当发现native泄漏后进行后续操作

    c.触发生成有coredump的db(执行完成后生成的文件位于/data/aee_exp文件夹下)

    adb shell aee -p $pid    或者  kill -11 $pid
    

    d.使用SpOfflineDebugSuite分析工具分析coredump。需要使用MTK的GAT工具解析dbg文件,多次解析后使用SpOfflineDebugSuite分析结果

    2.mmap内存泄漏分析(映射内存),当上述方法没有分析结果时,可以采用该方法:
    a.打开mmap debug机制复现

    adb shell setprop persist.debug.mmap.program app_process
    adb shell setprop persist.debug.mmap.config 0x22002010
    adb shell setprop persist.debug.mmap 1
    adb reboot
    
    若是P版本上,输入如下命令:
    
    adb shell setprop persist.vendor.debug.mmap.program app_process
    adb shell setprop persist.vendor.debug.mmap.config 0x22002010
    adb shell setprop persist.vendor.debug.mmap 1
    adb reboot
    

    b.检查是否存在内存泄漏。

    打开mtklogger,不断通过adb shell procrank -u > procrank.txt查看当前系统内存的使用情况。当看到被监控的进程占用内存(USS字段)超过了正常值很多,则可能存在内存泄漏。

    c. 得到该进程内存使用分布情况($pid为被监控进程pid)

    (1)adb shell dumpsys meminfo $pid >meminfo_$pid.txt
    
    (2)adb shell procmem $pid > procmem_$pid.txt
    
    (3)adb shell kill -11 $pid>生成DB
    

    d. 复现问题后使用SpOfflineDebugSuite分析,分析完coredump会提供分析报告。

    相关文章

      网友评论

          本文标题:内存泄漏分析(一)

          本文链接:https://www.haomeiwen.com/subject/cqikfltx.html