
1) 【一句话结论】:移动端内存泄漏导致应用崩溃的核心是对象被引用但不再被应用使用,通过LeakCanary等工具分析内存快照,定位泄漏根源(如静态集合、弱引用等),修改代码释放无效引用(如移除集合元素、使用弱引用),从而避免内存占用持续增长。
2) 【原理/概念讲解】:内存泄漏是指程序中不再被使用的对象仍然被引用,导致垃圾回收器(GC)无法回收,内存持续增长。在Android中,GC会定期回收无引用的对象,但若对象被静态变量、弱引用或持有其引用的集合等保留,就会泄漏。LeakCanary的工作原理是:在应用启动时注入监控,当检测到内存增长异常时,生成内存快照(记录当前所有对象及其引用关系),通过分析快照中的“泄漏对象”和“引用链”,定位泄漏的根源。类比:就像房间里的垃圾(对象)被锁在房间里(引用),垃圾回收员(GC)进不来,导致房间(内存)被占满,最终房间(应用)崩溃。
3) 【对比与适用场景】:
| 工具 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|
| LeakCanary | 自动内存泄漏检测工具 | 基于内存快照,自动分析 | Android应用,静态泄漏检测 | 需集成到项目,依赖反射 |
| Memory Profiler | Android官方内存分析工具 | 实时监控,可视化内存变化 | 动态内存分析,性能调优 | 需手动操作,实时性高 |
4) 【示例】:假设在Activity中持有静态集合的引用,导致内存泄漏。伪代码:
// 静态集合持有对象引用
static List<SomeObject> sLeakedObjects = new ArrayList<>();
// 在Activity中
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 创建对象并加入静态集合
SomeObject obj = new SomeObject();
sLeakedObjects.add(obj);
// ... 其他代码
}
// 当Activity销毁时,未移除集合中的对象
@Override
protected void onDestroy() {
super.onDestroy();
// 销毁时未清理集合,导致obj被静态集合引用
}
此时,即使Activity被销毁,obj仍然被sLeakedObjects持有,GC无法回收,导致内存泄漏。
5) 【面试口播版答案】:在移动端开发中,我遇到过因Activity持有静态集合引用导致的内存泄漏问题。首先,通过LeakCanary检测到内存持续增长,生成内存快照后,分析发现一个SomeObject对象被静态集合sLeakedObjects引用,而该Activity已销毁。定位到泄漏根源是静态集合未及时清理。解决方法是:在Activity销毁时移除集合中的对象,修改代码为:
@Override
protected void onDestroy() {
super.onDestroy();
sLeakedObjects.remove(obj); // 移除泄漏对象
}
同时,若集合是静态的,考虑使用弱引用(如WeakReference)或避免静态集合持有活动引用,避免后续泄漏。
6) 【追问清单】:
WeakReference的get()方法返回null后未移除)、静态变量持有活动引用、内部类持有外部对象引用。解决方法:及时清理弱引用、移除静态集合中的活动引用、避免内部类持有外部引用。7) 【常见坑/雷区】: