阅读 360

Android面试专题(八):内存泄漏

不诗意的女程序媛不是好厨师~ 转载请注明出处,From李诗雨—blog.csdn.net/cjm24848365…

1.内存泄漏的定义

  • 内存泄漏(Memory Leak):

    是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。

  • 产生的原因:

    一个长生命周期的对象持有一个短生命周期对象的引用

通俗讲就是: 该回收的对象,因为引用问题没有被回收,最终会产生OOM

2.内存泄漏的检测---使用Profiler

如果你觉得这些概念没有码农味的话,没关系,我们还有热腾腾的代码:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        MyThread t = new MyThread(this);
        t.start();
    }

    class MyThread extends Thread {
        Context context;

        MyThread(Context context) {
            this.context = context;//持有了MainActivity的对象
        }

        @Override
        public void run() {
            try {
                Thread.sleep(1000000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
复制代码

让我来解释一下这个代码的用意:

如代码,我们定义了一个线程MyThread类,它做的事情就是休眠1000s。然后我们在MainActivity的onCreate()方法中启动了这个线程。

现在我在 线程还在休眠的过程中 就退出MainActivity, 按说退出了,MainActivity就应该被销毁了才是。但是由于MyThread持有activity的引用 并且它还在休眠中 ,所以就会导致activity无法销毁,从而造成内存泄漏。

这里我们就模拟了 “一个长生命周期的对象持有一个短生命周期对象的引用”,MyThread充当了长生命周期的对象,MainActivity充当了段生命周期的对象。

为了能够更加直观的看到确实是内存泄漏了(即使退出了应用,MainActivity还没有被销毁).

下面我们使用Profiler工具来检测并证实一下确实存在内存泄漏:

在这里插入图片描述

退出应用后的内存情况展示:

在这里插入图片描述

按照如图所示,选中Memory,我们先退出自己的应用,然后过一小段时间,再截取一段时间来看看内存情况。

接着我们根据包名找到自己的应用,发现MainActivity确实没有被销毁并且还占用着内存。

所以,当一个长生命周期的对象持有一个短生命周期对象的引用时,

就会造成 该回收的对象,因为引用问题没有被回收,最终会产生OOM。

3.Java是如何处理内存泄漏的?

如果面试官问:“你知道Java是如何处理内存泄漏的吗?”

那我告诉你,面试官一定是在逗你玩的!

因为,Java本身根本不会去处理内存泄漏,内存泄漏需要我们自己去处理。

怎么处理,当然是利用工具(比如说Profiler、Android LeakCanary等),先检测并定位到内存泄漏的位置,然后去修复它了。

积累点滴,做好自己~