1.环境Android16,设备是userdebug2.使用下面命令检查是否有内存泄漏adb shell dumpsys meminfo --unreachable 26718其中26718是应用的进程号,输出如下Unreachable memory是native未回收的内存Applications Memory Usage (in Kilobytes):Uptime: 5082822 Realtime: 5082822** MEMINFO in pid 10085 [com.crab.test.kotlin.mediandktest] **Pss Private Private Swap Rss Heap Heap HeapTotal Dirty Clean Dirty Total Size Alloc Free------ ------ ------ ------ ------ ------ ------ ------Native Heap 12700 12700 0 0 12700 17772 11340 2492Dalvik Heap 9712 9712 0 0 9712 18880 9440 9440Dalvik Other 2968 2820 0 0 3116Stack 680 680 0 0 680Ashmem 625 0 0 0 1892Other dev 25 0 24 0 1104.so mmap 19525 7316 3012 0 100316.jar mmap 6018 0 368 0 66176.apk mmap 12186 28 10564 0 16260.ttf mmap 312 0 132 0 1264.dex mmap 197 8 0 0 1580.oat mmap 233 0 0 0 10708.art mmap 32913 32872 8 0 33188Other mmap 50662 2432 46804 0 55932Unknown 2916 2852 64 0 2916TOTAL 151672 71420 60976 0 317544 36652 20780 11932App SummaryPss(KB) Rss(KB)------ ------Java Heap: 42592 42900Native Heap: 12700 12700Code: 21452 196624Stack: 680 680Graphics: 0 0Private Other: 54972System: 19276Unknown: 64640TOTAL PSS: 151672 TOTAL RSS: 317544 TOTAL SWAP (KB): 0ObjectsViews: 17 ViewRootImpl: 1AppContexts: 5 Activities: 1Assets: 3 AssetManagers: 0Local Binders: 15 Proxy Binders: 65Parcel memory: 6 Parcel count: 25Death Recipients: 0 WebViews: 0Native AllocationsCount Total(kB)------ ------Other (malloced): 511 47Other (nonmalloced): 83 62Bitmap (malloced): 4 970SQLMEMORY_USED: 0PAGECACHE_OVERFLOW: 0 MALLOC_SIZE: 0Unreachable memory1797 bytes in 36 unreachable allocationsABI: arm6456 bytes unreachable at 796666c290referencing 1677 unreachable bytes in 34 allocationsfirst 32 bytes of contents:796666c290: d0 22 64 26 7b 00 00 b4 38 a1 60 96 7a 00 00 b4 .d{...8..z...796666c2a0: 08 97 9b e1 7b 00 00 00 00 00 00 00 00 00 00 00 ....{...........64 bytes unreachable at 7966612b50first 20 bytes of contents:7966612b50: 55 73 65 72 2d 41 67 65 6e 74 3a 20 73 74 61 67 User-Agent: stag7966612b60: 65 66 72 69 67 68 74 2f 31 2e 32 20 28 4c 69 6e efright/1.2 (Lin3.开启Malloc Debug(应用级别)根据文档路径(源码根目录/bionic/libc/memory/malloc_debug/README.md),For app developers 章节使用 wrap.包名 属性开启# 如果 Android 12 且遇到问题先执行这个修复命令可选adb shell setprop dalvik.vm.force-java-zygote-fork-loop true# 开启 malloc debug记录 backtraceadb shell setprop wrap.com.crab.test.kotlin.mediandktest LIBC_DEBUG_MALLOC_OPTIONSbacktrace logwrappercom.crab.test.kotlin.mediandktest是应用的包名验证属性是否设置成功adb shell getprop | grep wrap# 应该看到: wrap.com.crab.test.kotlin.mediandktest: [LIBC_DEBUG_MALLOC_OPTIONSbacktrace logwrapper]4.重复执行第二步可以看到下面输出Applications Memory Usage (in Kilobytes):Uptime: 11497639 Realtime: 11497639** MEMINFO in pid 26718 [com.crab.test.kotlin.mediandktest] **Pss Private Private Swap Rss Heap Heap HeapTotal Dirty Clean Dirty Total Size Alloc Free------ ------ ------ ------ ------ ------ ------ ------Native Heap 20016 20016 0 0 20016 25056 18276 2852Dalvik Heap 9572 9572 0 0 9572 18864 9432 9432Dalvik Other 2988 2844 0 0 3132Stack 884 884 0 0 884Ashmem 625 0 0 0 1892Other dev 656 0 24 0 2764.so mmap 27268 7436 9656 0 111332.jar mmap 6362 0 684 0 66596.apk mmap 12231 28 10592 0 16324.ttf mmap 312 0 132 0 1264.dex mmap 205 8 16 0 1580.oat mmap 272 0 16 0 10604.art mmap 32913 32872 8 0 33188Other mmap 50728 2496 46800 0 56068Unknown 2932 2868 64 0 2932TOTAL 167964 79024 67992 0 338148 43920 27708 12284App SummaryPss(KB) Rss(KB)------ ------Java Heap: 42452 42760Native Heap: 20016 20016Code: 28596 208016Stack: 884 884Graphics: 0 0Private Other: 55068System: 20948Unknown: 66472TOTAL PSS: 167964 TOTAL RSS: 338148 TOTAL SWAP (KB): 0ObjectsViews: 17 ViewRootImpl: 1AppContexts: 5 Activities: 1Assets: 3 AssetManagers: 0Local Binders: 15 Proxy Binders: 65Parcel memory: 6 Parcel count: 25Death Recipients: 0 WebViews: 0Native AllocationsCount Total(kB)------ ------Other (malloced): 511 47Other (nonmalloced): 83 62Bitmap (malloced): 4 970SQLMEMORY_USED: 0PAGECACHE_OVERFLOW: 0 MALLOC_SIZE: 0Unreachable memory1771 bytes in 33 unreachable allocationsABI: arm6456 bytes unreachable at 752815af80referencing 1651 unreachable bytes in 31 allocationsfirst 32 bytes of contents:752815af80: f0 b4 0b 78 75 00 00 b4 18 62 00 a8 75 00 00 b4 ...xu....b..u...752815af90: 08 37 56 9a 77 00 00 00 00 00 00 00 00 00 00 00 .7V.w...........#00 pc 00000000000596ec /apex/com.android.runtime/lib64/bionic/libc.so (malloc80)#01 pc 000000000010289c /system/lib64/libc.so (operator new(unsigned long)28)#02 pc 000000000007a158 /system/lib64/libmedia.so#03 pc 000000000002036c /system/lib64/libmediandk.so#04 pc 000000000001c724 /system/lib64/libstagefright_foundation.so (android::AHandler::deliverMessage(android::spandroid::AMessage const)184)#05 pc 000000000002373c /system/lib64/libstagefright_foundation.so (android::AMessage::deliver()172)#06 pc 000000000001dc24 /system/lib64/libstagefright_foundation.so (android::ALooper::loop()536)#07 pc 0000000000017e54 /system/lib64/libutils.so (android::Thread::_threadLoop(void*)536)#08 pc 0000000000137b68 /system/lib64/libandroid_runtime.so (android::AndroidRuntime::javaThreadShell(void*)144)#09 pc 0000000000019eec /system/lib64/libutils.so#10 pc 0000000000086580 /apex/com.android.runtime/lib64/bionic/libc.so#11 pc 0000000000078d64 /apex/com.android.runtime/lib64/bionic/libc.so64 bytes unreachable at 752801f580first 20 bytes of contents:752801f580: 55 73 65 72 2d 41 67 65 6e 74 3a 20 73 74 61 67 User-Agent: stag752801f590: 65 66 72 69 67 68 74 2f 31 2e 32 20 28 4c 69 6e efright/1.2 (Lin#00 pc 00000000000599bc /apex/com.android.runtime/lib64/bionic/libc.so (realloc160)#01 pc 0000000000028ca4 /system/lib64/libstagefright_foundation.so (android::AString::append(char const*, unsigned long)120)#02 pc 000000000002a2a0 /system/lib64/libstagefright_foundation.so#03 pc 000000000007ca58 /system/lib64/libmediaplayerservice.so#04 pc 0000000000059414 /apex/com.android.runtime/bin/linker64#05 pc 00000000000593c0 /apex/com.android.runtime/bin/linker64#06 pc 00000000000585fc /apex/com.android.runtime/bin/linker64#07 pc 0000000000057fc4 /apex/com.android.runtime/bin/linker64#08 pc 0000000000004024 /apex/com.android.runtime/lib64/bionic/libdl.so (dlopen16)#09 pc 00000000000fc890 /system/lib64/libaudioclient.so#10 pc 000000000005946c /system/lib64/libaudioclient.so#11 pc 0000000000059414 /apex/com.android.runtime/bin/linker64#12 pc 00000000000593c0 /apex/com.android.runtime/bin/linker64#13 pc 00000000000593c0 /apex/com.android.runtime/bin/linker64#14 pc 00000000000593c0 /apex/com.android.runtime/bin/linker64#15 pc 00000000000593c0 /apex/com.android.runtime/bin/linker645.从源码编译的out目录找到这些so库的符号链接去找到对应的文件行号比如Android16源码:android/prebuilts/clang/host/linux-x86/clang-r574158/bin$ ./llvm-addr2line -f -C -e libstagefright_foundation.so 000000000001dc24android::ALooper::loop()frameworks/av/media/module/foundation/ALooper.cpp:280android/prebuilts/clang/host/linux-x86/clang-r574158/bin$ ./llvm-addr2line -f -C -e libstagefright_foundation.so 000000000002373candroid::AMessage::deliver()frameworks/av/media/module/foundation/AMessage.cpp:419android/prebuilts/clang/host/linux-x86/clang-r574158/bin$ ./llvm-addr2line -f -C -e libstagefright_foundation.so 000000000001c724android::AHandler::deliverMessage(android::spandroid::AMessage const)frameworks/av/media/module/foundation/AHandler.cpp:28android/prebuilts/clang/host/linux-x86/clang-r574158/bin$ ./llvm-addr2line -f -C -e liblibmediandk.so libmedia.so libstagefright_foundation.soandroid/prebuilts/clang/host/linux-x86/clang-r574158/bin$ ./llvm-addr2line -f -C -e liblibmediandk.so libmedia.so libstagefright_foundation.soandroid/prebuilts/clang/host/linux-x86/clang-r574158/bin$ ./llvm-addr2line -f -C -e libmediandk.so 000000000002036cCodecHandler::onMessageReceived(android::spandroid::AMessage const)frameworks/av/media/ndk/NdkMediaCodec.cpp:258可以看到NdkMediaCodec.cpp:258泄漏了我的代码如下:case MediaCodec::CB_OUTPUT_FORMAT_CHANGED:{spAMessage format;if (!msg-findMessage(format, format)) {ALOGD(CB_OUTPUT_FORMAT_CHANGED: format is expected.);break;}AMediaFormat *aMediaFormat AMediaFormat_fromMsg(format);Mutex::Autolock _l(mCodec-mAsyncCallbackLock);if (mCodec-mAsyncCallback.onAsyncFormatChanged ! NULL) {mCodec-mAsyncCallback.onAsyncFormatChanged(mCodec,mCodec-mAsyncCallbackUserData,aMediaFormat);}break;}这里new了一个指针异步回调给了应用层应用层拿到这个指针没有释放由于系统层也没有释放所以就导致了内存泄漏。修改方法也很简单应用层拿到这个指针的时候在不需要使用时主动调用一次AMediaFormat_delete来释放指针就可以了。