news 2026/5/26 6:24:19

记一次Android进程native内存泄漏分析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
记一次Android进程native内存泄漏分析

1.环境

Android16,设备是userdebug

2.使用下面命令检查是否有内存泄漏

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 Heap
Total Dirty Clean Dirty Total Size Alloc Free
------ ------ ------ ------ ------ ------ ------ ------
Native Heap 12700 12700 0 0 12700 17772 11340 2492
Dalvik Heap 9712 9712 0 0 9712 18880 9440 9440
Dalvik Other 2968 2820 0 0 3116
Stack 680 680 0 0 680
Ashmem 625 0 0 0 1892
Other 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 33188
Other mmap 50662 2432 46804 0 55932
Unknown 2916 2852 64 0 2916
TOTAL 151672 71420 60976 0 317544 36652 20780 11932

App Summary
Pss(KB) Rss(KB)
------ ------
Java Heap: 42592 42900
Native Heap: 12700 12700
Code: 21452 196624
Stack: 680 680
Graphics: 0 0
Private Other: 54972
System: 19276
Unknown: 64640
TOTAL PSS: 151672 TOTAL RSS: 317544 TOTAL SWAP (KB): 0

Objects
Views: 17 ViewRootImpl: 1
AppContexts: 5 Activities: 1
Assets: 3 AssetManagers: 0
Local Binders: 15 Proxy Binders: 65
Parcel memory: 6 Parcel count: 25
Death Recipients: 0 WebViews: 0

Native Allocations
Count Total(kB)
------ ------
Other (malloced): 511 47
Other (nonmalloced): 83 62
Bitmap (malloced): 4 970

SQL
MEMORY_USED: 0
PAGECACHE_OVERFLOW: 0 MALLOC_SIZE: 0

Unreachable memory
1797 bytes in 36 unreachable allocations
ABI: 'arm64'

56 bytes unreachable at 796666c290
referencing 1677 unreachable bytes in 34 allocations
first 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 7966612b50
first 20 bytes of contents:
7966612b50: 55 73 65 72 2d 41 67 65 6e 74 3a 20 73 74 61 67 User-Agent: stag
7966612b60: 65 66 72 69 67 68 74 2f 31 2e 32 20 28 4c 69 6e efright/1.2 (Lin

3.开启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,记录 backtrace

adb shell setprop wrap.com.crab.test.kotlin.mediandktest '"LIBC_DEBUG_MALLOC_OPTIONS=backtrace logwrapper"'
com.crab.test.kotlin.mediandktest是应用的包名

验证属性是否设置成功:
adb shell getprop | grep wrap

# 应该看到: wrap.com.crab.test.kotlin.mediandktest: [LIBC_DEBUG_MALLOC_OPTIONS=backtrace 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 Heap
Total Dirty Clean Dirty Total Size Alloc Free
------ ------ ------ ------ ------ ------ ------ ------
Native Heap 20016 20016 0 0 20016 25056 18276 2852
Dalvik Heap 9572 9572 0 0 9572 18864 9432 9432
Dalvik Other 2988 2844 0 0 3132
Stack 884 884 0 0 884
Ashmem 625 0 0 0 1892
Other 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 33188
Other mmap 50728 2496 46800 0 56068
Unknown 2932 2868 64 0 2932
TOTAL 167964 79024 67992 0 338148 43920 27708 12284

App Summary
Pss(KB) Rss(KB)
------ ------
Java Heap: 42452 42760
Native Heap: 20016 20016
Code: 28596 208016
Stack: 884 884
Graphics: 0 0
Private Other: 55068
System: 20948
Unknown: 66472
TOTAL PSS: 167964 TOTAL RSS: 338148 TOTAL SWAP (KB): 0

Objects
Views: 17 ViewRootImpl: 1
AppContexts: 5 Activities: 1
Assets: 3 AssetManagers: 0
Local Binders: 15 Proxy Binders: 65
Parcel memory: 6 Parcel count: 25
Death Recipients: 0 WebViews: 0

Native Allocations
Count Total(kB)
------ ------
Other (malloced): 511 47
Other (nonmalloced): 83 62
Bitmap (malloced): 4 970

SQL
MEMORY_USED: 0
PAGECACHE_OVERFLOW: 0 MALLOC_SIZE: 0

Unreachable memory
1771 bytes in 33 unreachable allocations
ABI: 'arm64'

56 bytes unreachable at 752815af80
referencing 1651 unreachable bytes in 31 allocations
first 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 (malloc+80)
#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::sp<android::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.so

64 bytes unreachable at 752801f580
first 20 bytes of contents:
752801f580: 55 73 65 72 2d 41 67 65 6e 74 3a 20 73 74 61 67 User-Agent: stag
752801f590: 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 (realloc+160)
#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 (dlopen+16)
#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/linker64

5.从源码编译的out目录找到这些so库的符号链接,去找到对应的文件行号

比如Android16源码:

android/prebuilts/clang/host/linux-x86/clang-r574158/bin$ ./llvm-addr2line -f -C -e libstagefright_foundation.so 000000000001dc24
android::ALooper::loop()
frameworks/av/media/module/foundation/ALooper.cpp:280
android/prebuilts/clang/host/linux-x86/clang-r574158/bin$ ./llvm-addr2line -f -C -e libstagefright_foundation.so 000000000002373c
android::AMessage::deliver()
frameworks/av/media/module/foundation/AMessage.cpp:419
android/prebuilts/clang/host/linux-x86/clang-r574158/bin$ ./llvm-addr2line -f -C -e libstagefright_foundation.so 000000000001c724
android::AHandler::deliverMessage(android::sp<android::AMessage> const&)
frameworks/av/media/module/foundation/AHandler.cpp:28
android/prebuilts/clang/host/linux-x86/clang-r574158/bin$ ./llvm-addr2line -f -C -e lib
libmediandk.so libmedia.so libstagefright_foundation.so
android/prebuilts/clang/host/linux-x86/clang-r574158/bin$ ./llvm-addr2line -f -C -e lib
libmediandk.so libmedia.so libstagefright_foundation.so
android/prebuilts/clang/host/linux-x86/clang-r574158/bin$ ./llvm-addr2line -f -C -e libmediandk.so 000000000002036c
CodecHandler::onMessageReceived(android::sp<android::AMessage> const&)
frameworks/av/media/ndk/NdkMediaCodec.cpp:258

可以看到NdkMediaCodec.cpp:258泄漏了,我的代码如下:

case MediaCodec::CB_OUTPUT_FORMAT_CHANGED:
{
sp<AMessage> 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来释放指针就可以了。


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/26 6:23:02

从零搭建 Prometheus + Grafana 监控平台全攻略

从零搭建 Prometheus Grafana 监控平台全攻略 从零搭建 PrometheusGrafana 监控平台&#xff1a;从部署到告警全攻略 在云原生和容器化普及的当下&#xff0c;一套高效的监控体系是保障系统稳定运行的核心。Prometheus 作为开源的时序数据监控工具&#xff0c;凭借其灵活的查询…

作者头像 李华
网站建设 2026/5/26 6:22:33

PowerSetting极速下载优化方案全解析

问题背景与现状分析当前PowerSetting下载速度慢的具体表现&#xff08;如平均下载时长、用户反馈数据&#xff09;影响因素分析&#xff08;服务器带宽限制、跨地域访问延迟、网络拥塞等&#xff09;CDN加速技术方案CDN节点部署策略&#xff1a;全球边缘节点覆盖与智能调度动态…

作者头像 李华
网站建设 2026/5/26 6:18:59

银行柜面常见还款状态

正常未还&#xff1a;当期账单待还款&#xff0c;未逾期已结清&#xff1a;款项全额还款完毕部分还款&#xff1a;仅偿还部分金额&#xff0c;仍有欠款逾期&#xff1a;超出还款日未还款提前还款&#xff1a;未到约定日期主动还款还款中&#xff1a;交易提交&#xff0c;账务待…

作者头像 李华
网站建设 2026/5/26 6:11:29

LLM成本优化实战:从提示词到缓存,97%成本削减策略详解

1. 项目概述&#xff1a;从“烧钱”到“省钱”的LLM成本革命最近和几个做AI应用的朋友聊天&#xff0c;大家不约而同地提到了同一个痛点&#xff1a;大语言模型&#xff08;LLM&#xff09;的API调用成本&#xff0c;简直像是个无底洞。一个看似简单的对话应用&#xff0c;随着…

作者头像 李华
网站建设 2026/5/26 6:06:29

五个必刷Web渗透靶场:从手工注入到业务逻辑漏洞实战

1. 这五个靶场不是“玩具”&#xff0c;而是你渗透能力的体检报告单刚入行那会儿&#xff0c;我见过太多人把靶场当通关游戏——装完DVWA点几下SQL注入就截图发朋友圈&#xff1a;“拿下&#xff01;”。结果第一次真实红队演练&#xff0c;面对一个连报错都藏得严严实实的Web系…

作者头像 李华