相信大家对[App的内存管理][6]都是相当关心的,在项目上线前的几天时间也会借助相关工具突击下严重的泄漏问题;
针对内存泄漏先提出几个疑问:
- 什么是内存泄漏?
- 内存泄漏带来的危害又是什么?
- 哪些代码的写法会导致内存泄漏?
- 如何找到泄露的地方,以及如何修复它?
一、什么是内存泄漏?
- 无用的对象没有被及时释放引用,导致GC无法回收,就有可能出现内存泄漏。
二、内存泄漏带来的危害是什么?
- 内存泄漏会增加内存占用和OOM几率。
三、哪些代码的写法会导致内存泄漏?
常见五种导致 APP 内存泄漏的地方
静态 Activity
泄漏 activity 最简单的方法就是在 activity 类中定义一个 static 变量,并且将其指向一个运行中的 activity 实例。如果在 activity 的生命周期结束之前,没有清除这个引用,那它就会泄漏了。这是因为 activity(例如 MainActivity) 的类对象是静态的,一旦加载,就会在 APP 运行时一直常驻内存,因此如果类对象不卸载,其静态成员就不会被垃圾回收。void setStaticActivity() { activity = this; } View saButton = findViewById(R.id.sa_button); saButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { setStaticActivity(); nextActivity(); } });
内部类或者匿名内部类
类似的,匿名类同样会持有定义它们的对象的引用。因此如果在 activity 内定义了一个匿名的 AsyncTask 对象,就有可能发生内存泄漏了。如果 activity 被销毁之后 AsyncTask 仍然在执行,那就会组织垃圾回收器回收 activity 对象,进而导致内存泄漏,直到执行结束才能回收 activity。void startAsyncTask() { new AsyncTask
() { @Override protected Void doInBackground(Void... params) {while(true); } }.execute(); } super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); View aicButton = findViewById(R.id.at_button); aicButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startAsyncTask(); nextActivity(); } });