You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LeakCanary检测到Activity因mLoadedApk内存泄漏,无法定位问题原因

Android Activity 内存泄漏问题解决

问题背景

开发中遇到InstagramActivity内存泄漏问题,已接入LeakCanary检测,无法识别日志中提到的系统变量mLoadedApk、mReceivers,也无法定位泄漏根因。LeakCanary堆分析日志如下:

D/LeakCanary: ​
====================================
HEAP ANALYSIS RESULT
====================================
1 APPLICATION LEAKS

References underlined with "~~~" are likely causes.
Learn more at https://squ.re/leaks.

968964 bytes retained by leaking objects
Signature: a29bf580df87c6f6ad305a8d9f7b3bc3a01ea992
┬───
│ GC Root: System class
│
├─ android.provider.FontsContract class
│    Leaking: NO (GetDataFromServer↓ is not leaking and a class is never leaking)
│    ↓ static FontsContract.sContext
├─ instant.saver.for_instagram.api.GetDataFromServer instance
│    Leaking: NO (Application is a singleton)
│    mBase instance of android.app.ContextImpl
│    ↓ Application.mLoadedApk
│                  ~~~~~~~~~~
├─ android.app.LoadedApk instance
│    Leaking: UNKNOWN
│    Retaining 1.8 kB in 31 objects
│    mApplication instance of instant.saver.for_instagram.api.GetDataFromServer
│    Receivers
│    ..InstagramActivity@316939088
│    ....InstagramActivity$2@322490448
│    ..GetDataFromServer@316729128
│    ....VisibilityTracker@322489032
│    ↓ LoadedApk.mReceivers
│                ~~~~~~~~~~
├─ android.util.ArrayMap instance
│    Leaking: UNKNOWN
│    Retaining 1.3 kB in 18 objects
│    ↓ ArrayMap.mArray
│               ~~~~~~
├─ java.lang.Object[] array
│    Leaking: UNKNOWN
│    Retaining 1.3 kB in 16 objects
│    ↓ Object[].[0]
│               ~~~
╰→ instant.saver.for_instagram.InstagramActivity instance
​     Leaking: YES (ObjectWatcher was watching this because instant.saver.for_instagram.InstagramActivity received
​     Activity#onDestroy() callback and Activity#mDestroyed is true)
​     Retaining 969.0 kB in 17175 objects
​     key = 20591e0c-1b12-4810-bc0c-50d74a008298
​     watchDurationMillis = 14793
​     retainedDurationMillis = 9769
​     mApplication instance of instant.saver.for_instagram.api.GetDataFromServer
​     mBase instance of androidx.appcompat.view.ContextThemeWrapper
====================================
0 LIBRARY LEAKS

A Library Leak is a leak caused by a known bug in 3rd party code that you do not have control over.
See https://square.github.io/leakcanary/fundamentals-how-leakcanary-works/#4-categorizing-leaks
====================================
0 UNREACHABLE OBJECTS

An unreachable object is still in memory but LeakCanary could not find a strong reference path
from GC roots.
====================================
METADATA

Please include this in bug reports and Stack Overflow questions.

Build.VERSION.SDK_INT: 30
Build.MANUFACTURER: OnePlus
LeakCanary version: 2.7
App process name: instant.saver.for_instagram
Stats: LruCache[maxSize=3000,hits=3479,misses=88288,hitRate=3%]
RandomAccess[bytes=4242256,reads=88288,travel=46629354274,range=25009860,size=31821126]
Heap dump reason: 4 retained objects, app is not visible
Analysis duration: 5231 ms
Heap dump file path: /storage/emulated/0/Download/leakcanary-instant.saver.for_instagram/2021-11-10_11-02-28_887.hprof
Heap dump timestamp: 1636522400108
Heap dump duration: 45952 ms
====================================

核心变量说明

你业务代码中没有声明的mLoadedApk和mReceivers都是Android Framework层的内置变量,作用如下:

  • mLoadedApk:Application/ContextImpl的成员变量,是应用进程全局唯一的实例,存储当前APK加载的所有上下文信息、资源、组件注册记录等
  • mReceivers:LoadedApk的成员变量,类型为ArrayMap,系统用来存储整个应用所有动态注册的广播接收器的注册记录

泄漏根因定位

从日志的引用链可以明确泄漏路径:

系统FontsContract静态类 -> 静态变量sContext -> GetDataFromServer网络请求单例 -> mLoadedApk -> mReceivers广播注册列表 -> InstagramActivity实例

泄漏由两个问题共同导致:

  1. 网络请求单例GetDataFromServer错误传入了InstagramActivity的上下文,被系统静态类间接持有,单例生命周期和应用进程一致,不会被GC回收
  2. InstagramActivity内部动态注册了匿名广播接收器(日志中的InstagramActivity$2就是该匿名内部类实例),Activity销毁前没有调用unregisterReceiver()反注册,系统的mReceivers列表会一直持有该接收器的引用,而匿名内部类默认持有外部Activity的引用,最终导致Activity销毁后无法被回收

修复方案

  1. 修正单例上下文传入:GetDataFromServer单例初始化时必须传入Application的全局上下文,禁止传入Activity、Service等短生命周期组件的上下文
  2. 补充广播反注册逻辑:在InstagramActivity的onDestroy()(对应onCreate中注册)或onStop()(对应onStart中注册)中调用反注册方法,移除系统对广播接收器的持有
  3. 补充回调清理逻辑:如果InstagramActivity给GetDataFromServer设置了请求回调,需要在Activity销毁前将回调置空,避免匿名回调持有Activity引用

内容的提问来源于stack exchange,提问作者Roshan Kumar Nayak.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 14:54:08