AutofillClientController致Activity内存泄漏:系统问题还是实现问题?
旋转模拟器导致ExampleActivity内存泄漏,求助排查思路
旋转模拟器时出现如下内存泄漏问题,无法明确根源,怀疑是系统的AutofillClientController导致ExampleActivity泄漏,恳请各位提供排查思路!
测试环境
- Pixel 7 Pro API 34
- Pixel 4 API 31
- Pixel 3a API 28
- Pixel 4 API 21(泄漏报告细节略有不同,但推测原因一致)
- LeakCanary 2.13
LeakCanary泄漏分析报告
┬─── │ GC根:系统类 │ ├─ android.provider.FontsContract 类 │ 未泄漏:否(ExampleApplication↓ 未泄漏,且类永远不会泄漏) │ ↓ 静态字段 FontsContract.sContext ├─ com.example.ExampleApplication 实例 │ 未泄漏:否(Application是单例) │ mBase 是 android.app.ContextImpl 的实例 │ ↓ Application.mLoadedApk │ ~~~~~~~~~~ ├─ android.app.LoadedApk 实例 │ 泄漏状态:未知 │ 保留206.8 kB,涉及4052个对象 │ mApplication 是 com.example.ExampleApplication 的实例 │ 接收器列表: │ ..ExampleApplication@321728936 │ ....VisibilityTracker@329242680 │ ....aF@329242760 │ ....d@329242824 │ ....RF@329242896 │ ....ProxyChangeListener$ProxyReceiver@329242968 │ ↓ LoadedApk.mServices │ ~~~~~~~~~ ├─ android.util.ArrayMap 实例 │ 泄漏状态:未知 │ 保留203.2 kB,涉及4011个对象 │ ↓ ArrayMap.mArray │ ~~~~~~ ├─ java.lang.Object[] 数组 │ 泄漏状态:未知 │ 保留203.2 kB,涉及4009个对象 │ ↓ Object[2] │ ~~~ ├─ android.app.ContextImpl 实例 │ 泄漏状态:未知 │ 保留6.2 kB,涉及86个对象 │ mOuterContext 是 android.app.ContextImpl 的实例 │ ContextImpl.mOuterContext == ContextImpl.this:未绑定到任何特定生命周期 │ ↓ ContextImpl.mAutofillClient │ ~~~~~~~~~~~~~~~ ├─ android.view.autofill.AutofillClientController 实例 │ 泄漏状态:未知 │ 保留26 B,涉及1个对象 │ mActivity 是 com.example.ui.ExampleActivity 的实例,且 mDestroyed = true │ ↓ AutofillClientController.mActivity │ ~~~~~~~~~ ╰→ com.example.ui.ExampleActivity 实例 泄漏状态:是(ObjectWatcher监测到该对象,因为com.example.ui.ExampleActivity已收到Activity#onDestroy()回调,且Activity#mDestroyed为true) 保留51.8 kB,涉及1004个对象 key = a1f4ff6a-48ea-4ba9-90c4-7f746b99af89 watchDurationMillis = 7757 retainedDurationMillis = 2755 mApplication 是 com.example.ExampleApplication 的实例 mBase 是 androidx.appcompat.view.ContextThemeWrapper 的实例 元数据 Build.VERSION.SDK_INT: 34 Build.MANUFACTURER: Google LeakCanary版本: 2.13 应用进程名: com.example 类数量: 35752 实例数量: 351728 基本类型数组数量: 189083 对象数组数量: 44181 线程数量: 64 堆总字节数: 39264516 Bitmap数量: 35 Bitmap总字节数: 2247331 大Bitmap数量: 0 大Bitmap总字节数: 0 统计信息: LruCache[maxSize=3000,hits=166095,misses=321890,hitRate=34%] RandomAccess[bytes=15827352,reads=321890,travel=107139495512,range=47678011,size=58241724] 分析耗时: 26210 ms
排查思路
核查Autofill相关逻辑
- 检查ExampleActivity中是否主动启用Autofill功能,比如调用
setAutofillHints()或自定义AutofillCallback,确保在onDestroy()中清理相关引用,取消注册回调。 - 检查布局内EditText等控件是否设置了
autofillHints属性,系统Autofill服务可能会持有这些控件所在Activity的引用。
- 检查ExampleActivity中是否主动启用Autofill功能,比如调用
禁用Autofill验证泄漏根源
- 在测试设备手动关闭系统Autofill服务(设置→系统→语言和输入法→高级→自动填充服务),重新测试旋转场景,若泄漏消失则可确认是系统Autofill服务问题。
- 也可在应用内临时禁用Autofill:在Activity的
onCreate()中调用getWindow().getDecorView().setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS),验证泄漏是否缓解。
排查Context引用问题
- 从泄漏链看,LoadedApk的mServices持有ContextImpl进而关联到AutofillClientController,检查应用内全局单例或静态对象是否意外持有Activity Context,而非Application Context。
- 确认所有需Context的场景,比如注册广播接收器、初始化第三方库时,是否误用Activity Context,改用Application Context可避免生命周期绑定问题。
系统版本适配差异排查
- 对比API 21与其他版本的泄漏链差异,确认是否是系统Autofill服务在不同版本的实现差异导致泄漏。
- 查阅Android官方文档,确认对应版本Autofill相关API的行为变化,是否存在已知内存泄漏问题及官方修复方案。
进一步定位泄漏点
- 使用Android Studio Profiler记录旋转前后的堆快照,对比Activity实例的引用链,找到更具体的泄漏路径。
- 在ExampleActivity的
onDestroy()中打印可能的引用持有者,或用弱引用跟踪哪些对象仍持有Activity引用。
内容的提问来源于stack exchange,提问作者Oscar Spruit
相关产品推荐
相关产品推荐

