内存泄漏是指程序中已分配的内存由于某种原因未释放或无法释放,导致可用内存逐渐减少,最终可能引发OOM(Out Of Memory)崩溃。
常见内存泄漏场景
1. 静态变量持有Activity/Context引用
javapublic 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. 非静态内部类/匿名内部类
javapublic 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. 集合中的对象引用
javastatic List<Activity> activityList = new ArrayList<>(); // 添加Activity但不移除 activityList.add(activity);
内存泄漏检测工具
1. Android Studio Memory Profiler
- 实时监控内存分配
- 堆转储(Heap Dump)分析
- 查看对象引用链
2. LeakCanary
groovydependencies { 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
javaprivate 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组件
javaclass MyObserver implements DefaultLifecycleObserver { @Override public void onDestroy(LifecycleOwner owner) { // 自动清理 } }
面试要点
- 理解Java内存模型和GC机制
- 掌握引用类型:强引用、软引用、弱引用、虚引用
- 熟悉常见泄漏场景和解决方案
- 能够使用工具分析和定位泄漏
- 了解Android内存优化最佳实践