乐闻世界logo
搜索文章和话题

Android中内存泄漏的常见场景有哪些,如何检测和避免?

3月7日 12:12

内存泄漏是指程序中已分配的内存由于某种原因未释放或无法释放,导致可用内存逐渐减少,最终可能引发OOM(Out Of Memory)崩溃。

常见内存泄漏场景

1. 静态变量持有Activity/Context引用

java
public class Singleton { private static Singleton instance; private Context context; private Singleton(Context context) { this.context = context; // 泄漏!持有Activity引用 } // 解决方案:使用ApplicationContext private Singleton(Context context) { this.context = context.getApplicationContext(); } }

2. 非静态内部类/匿名内部类

java
public class MainActivity extends Activity { private Handler handler = new Handler() { // 非静态内部类 @Override public void handleMessage(Message msg) { // 持有外部Activity引用 } }; } // 解决方案:使用静态内部类 + WeakReference private static class MyHandler extends Handler { private WeakReference<Activity> weakRef; MyHandler(Activity activity) { weakRef = new WeakReference<>(activity); } }

3. 未取消注册的监听器和广播

java
// 内存泄漏示例 registerReceiver(receiver, filter); // 忘记在onDestroy中unregisterReceiver // 解决方案 @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(receiver); }

4. 资源未关闭

  • 数据库Cursor未关闭
  • IO流未关闭
  • Bitmap未回收

5. 集合中的对象引用

java
static List<Activity> activityList = new ArrayList<>(); // 添加Activity但不移除 activityList.add(activity);

内存泄漏检测工具

1. Android Studio Memory Profiler

  • 实时监控内存分配
  • 堆转储(Heap Dump)分析
  • 查看对象引用链

2. LeakCanary

groovy
dependencies { debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.x' }
  • 自动检测内存泄漏
  • 生成泄漏引用链
  • 通知提示泄漏信息

3. MAT(Memory Analyzer Tool)

  • 分析hprof文件
  • 查找支配树(Dominator Tree)
  • 识别泄漏嫌疑对象

内存泄漏避免策略

1. 使用ApplicationContext

java
// 当不需要Activity特性时 Intent intent = new Intent(getApplicationContext(), Target.class);

2. 及时释放资源

java
@Override protected void onDestroy() { super.onDestroy(); // 移除Handler消息和回调 handler.removeCallbacksAndMessages(null); // 取消网络请求 call.cancel(); // 注销监听器 sensorManager.unregisterListener(listener); }

3. 使用WeakReference

java
private static class MyAsyncTask extends AsyncTask<Void, Void, Void> { private WeakReference<Activity> weakActivity; MyAsyncTask(Activity activity) { weakActivity = new WeakReference<>(activity); } @Override protected Void doInBackground(Void... voids) { // 后台任务 return null; } @Override protected void onPostExecute(Void result) { Activity activity = weakActivity.get(); if (activity != null && !activity.isFinishing()) { // 更新UI } } }

4. 使用Lifecycle组件

java
class MyObserver implements DefaultLifecycleObserver { @Override public void onDestroy(LifecycleOwner owner) { // 自动清理 } }

面试要点

  • 理解Java内存模型和GC机制
  • 掌握引用类型:强引用、软引用、弱引用、虚引用
  • 熟悉常见泄漏场景和解决方案
  • 能够使用工具分析和定位泄漏
  • 了解Android内存优化最佳实践
标签:Android