当前位置: 首页 > 科技观察

研究了一波AndroidNativeC++内存泄露的调试

时间:2023-03-19 02:05:01 科技观察

文末,本文转载自微信公众号《程序喵大师》,作者程序喵大师。转载本文请联系程序大师喵公众号。最近在调试AndroidNative层的内存泄漏问题。整理了一些笔记,分享这篇文章。如何查看内存信息?Android按键记忆项目,启动一个线程,每隔一定时间打印出当前内存信息【获取内存信息的API有很多,这里只列出一个,亲测有效】privatevoidstartMemProfiler(){newThread(newRunnable(){@Overridepublicvoidrun(){while(true){displayMemory();try{Thread.sleep(2000);}catch(InterruptedExceptione){e.printStackTrace();}}}}).start();}privatevoiddisplayMemory(){finalActivityManageractivityManager=(ActivityManager)getSystemService(ACTIVITY_SERVICE);ActivityManager.MemoryInfoinfo=newActivityManager.MemoryInfo();activityManager.getMemoryInfo(info);Log.i(TAG,"剩余系统内存:"+(info.availMem/(1024*1024))+"M");Log.i(TAG,"系统是否低内存运行:"+info.lowMemory);Log.i(TAG,"当系统剩余内存低于"+(info.threshold/(1024*1024))+"M"+"会被视为低内存运行");Log.i(TAG,"系统分配的本机内存:"+(Debug.getNativeHeapAllocatedSize()/(1024*1024))+"M");Log.i(TAG,"系统剩余本机内存:"+(Debug.getNativeHeapFreeSize()/(1024*1024))+"M");Log.i(TAG,"系统所有本机内存大小:"+(Debug.getNativeHeapSize()/(1024*1024))+"M");}使用adb命令行adbshel??ldumpsysmeminfo/adbshel??ldumpsysmeminfo/adbshel??ldumpsysmeminfotv.danmaku.bilidumpsysmeminfo显示信息如图:Android按键内存项介绍这里只介绍需要关注的字段:DalvikHeap:虚拟机占用的内存,可以理解为Java层占用的内存NativeHeap:Native层占用的堆内存可以理解为C/C++端占用的内存。【需要关注的项目】PrivateDirty/Clean:进程私有的内存。进程销毁后,可以回收这部分内存【Dirty/Clean:页面是否被修改,如果被修改,则为脏,在该页面被淘汰时,该页面将被换出。】VSS(VirtualSetSize):表示一个进程可以访问的所有内存地址空间的大小。此大小包括进程已请求但尚未使用的内存空间。实际中很少用这种方式来表示一个进程的内存使用情况,用它来表示单个进程的内存使用情况是不准确的。【图中没有显示,但是linux里面有这个东西】RSS(ResidentSetSize):表示一个进程在RAM中实际使用的空间地址大小,包括所有共享库占用的内存。这表示进程占用的内存也不准确。【图中没有显示,但是linux里面有这个东西】PSS(ProportionalSetSize):表示一个进程实际使用的空间地址在RAM中的大小,其中按比例包含了共享库占用的内存。如果有3个进程使用同一个共享库,那么每个进程的PSS包括共享库内存的1/3。这种方式更准确的表示了进程的内存使用情况,但是当只有一个进程使用共享库时,情况就和RSS完全一样了。[PSS测量的一个优点是可以将所有进程的PSS相加,以确定所有进程实际占用的内存。这意味着PSS是衡量进程实际RAM使用量的理想方法,以及它相对于其他进程如何使用RAM以及可用RAM总量。]USS(UniqueSetSize):表示进程本身占用的内存空间大小,不包括任何其他组件。这是指示进程内存大小的最佳方式!【图中没有显示,但是linux里面有这个东西】【所以有:VSS>=RSS>=PSS>=USS】Graphics:Graphicsbufferqueue是用来显示像素(包括GL表面,GL纹理)的内存等)到屏幕。(请注意这是与CPU共享的内存,不是GPU专用内存。)【官方文档是这么说的,具体意思我不明白,https://developer.android.com/studio/profile/memory-profiler]如果想了解其他字段,可以参考官方文档:https://developer.android.com/studio/command-line/dumpsys如何通过消除法+打印当前内存来调试内存泄漏信息(如上所述),有疑虑的地方注释掉,看看会不会有漏洞[比较粗略]。代码层全局覆盖malloc和free。其实质就是记录每一个malloc节点,存入链表。当空闲时,节点从链表中删除。如果链表最后还有结点,说明存在内存泄漏。【大部分场景好用,但只能检测当前代码内存中的C语言代码,不能检测其他库中的泄漏】重载operatornew和operatordelete,原理和上面类似。【只能检测C++使用newdelete操作的内存,不能检测malloc和free操作的内存】使用AndroidStudioProfiler工具:需要Android10以上,详见:https://developer.android.com/studio/profile/内存分析器。【整体感觉不是很好用】Demo端集成了tencent/matrix,可以选择hook某个动态链接库下的malloc和freesymbols。如果发现某个动态链接库有内存泄漏,就会打印泄漏的堆栈信息。[推荐使用]matrix的使用可以选择通过集成matrix库来hook一个动态链接库的malloc和freesymbols,然后工作方式类似libctools,存储malloc节点,空闲时删除该节点,最后计算内存泄漏。.matrix的集成方法可以看github库:https://github.com/Tencent/matrixhook原理可以看:https://github.com/iqiyi/xHook/blob/master/docs/overview/android_plt_hook_overview.zh-CN.md中如果有内存泄漏,会有json和log后缀的文件,如图:json文件会统计哪个库泄漏了多少内存,log文件会记录具体泄露的堆栈信息。得到具体泄露的堆栈信息后,可以使用addr2line工具定位具体代码:/Users/xxx/Android/ndk/21.4.7075529/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android-addr2line-C-f-e/Users/xxx/project/java/build/intermediates/stripped_native_libs/debug/out/lib/arm64-v8a/libBMMCapture-Android.so83a70效果如图:其他工具dumpsys还有一些其他功能,用法如下:memoryadbshelldumpsysmeminfoCPUadbshelldumpsyscpuinfoframerateadbshelldumpsysgfxinfodisplayadbshelldumpsysdisplaypoweradbshelldumpsyspowerbatterystatusadbshelldumpsysbatterystatsbatteryadbshelldumpsysbatteryalarmclockadbshelldumpsys报警位置adblocdumpsy内存泄漏排查背景:每次发生内存泄漏,往往怀疑是某个模块或其他库更新引起的,但没有证据,也没有合适的方法论来解决问题内存泄漏。分析及解决方案:在访问各个第三方库时,写一个demo,进行效果测试,内存测试,性能测试,每次更新第三方库时运行demo。或者每次出问题,运行demo看看是不是这个库的问题。集成第三方库时,降低代码耦合度,保证第三方库灵活移除。可以考虑条件编译等手段,方便排查问题。介绍检查工具:○内存泄漏:Android使用matrix,iOS使用Xcode○Cpu占用率:Androidprofiler,iOSXcode○Gpu占用率:Android高通使用snapdragonprofiler,或者perfdog(付费)相关资料推荐https://developer.android.com/topic/performance/memory-management?hl=zh-cnhttps://developer.android.com/studio/profile/memory-profilerhttps://developer.android.com/studio/command-line/dumpsyshttps://developer.android.com/studio/profile/memory-profilerhttps://developer.android.com/studio/command-line/dumpsyshttps://github.com/iqiyi/xHook/blob/master/docs/overview/android_plt_hook_overview.zh-CN.md参考资料https://developer.android.com/studio/command-line/dumpsyshttps://blog。csdn。net/pugongying1988/article/details/16838859https://www.jianshu.com/p/8203457a11cc