美文网首页
说说 内存泄漏

说说 内存泄漏

作者: 日三省 | 来源:发表于2016-07-19 23:59 被阅读137次

    内存泄漏和内存溢出是两个概念。
    内存泄漏,指的是程序使用过的内存“忘记”归还给系统,造成长时间无谓地占用。
    内存溢出,指的是内存被大量的使用后,程序再次去申请内存时,系统已经不能满足其要求的情况。
    所以,内存泄露到一定程度就会导致内存溢出。

    Java中,内存的回收工作是GC来做的。GC也有软肋:如果持有对象的强引用,GC是无法在内存中回收这个对象的。

    绕个远说说几种引用:

    • 强引用(StrongReference)
      强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。
    • 软引用(SoftReference)
      如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。
    • 弱引用(WeakReference)
      GC扫描过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。
    • 虚引用(PhantomReference)
      如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。

    列举经常造成内存泄漏的几种情况:

    1. static变量
    • static activity
    public class MyActivity extends BaseActivity {
        static Activity mActivity = null;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mActivity = this;
        }
    }
    

    通常,一个activity对象包含了大量的引用,如果赋值给一个静态变量会使activity脱离系统的管理。被泄漏的activity对象会一直存活在内存中,造成内存泄漏。

    • static view
    public class MyActivity extends BaseActivity {
        static TextView textView = null;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            textView = new TextView(this);
        }
    }
    
    1. 内部类
      内部类使用起来是比较便捷的,但就是这么一点福利也要冒着内存泄漏的风险,因为非静态的内部类会持有外部类的一个隐式引用。
    • Thread
    public class MyActivity extends BaseActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            doSth();
        }
    
        private void doSth() {
            new Thread() {
                @Override
                public void run() {
                    while (true) {
                        SystemClock.sleep(1000);
                    }
                }
            }.start();
        }
    }
    

    假如新线程执行的任务非常耗时,十天半个月都做不完。在此期间,外部类对象也不能被回收。TimerTask和AsyncTask也会有同样的问题。

    • Handler
    public class MyActivity extends BaseActivity {
    
        Handler mHanlder = new Handler();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            doSth();
        }
    
        private void doSth() {
            mHanlder.postDelayed(new Runnable() {
                @Override
                public void run() {
    
                }
            }, Long.MAX_VALUE >> 1);
        }
    }
    

    Runnable会持有外部类引用,造成内存泄漏。

    1. Sensor Manager
      通过Context.getSystemService(int name)可以获取系统服务。这些服务工作在各自的进程中,帮助应用处理后台任务,处理硬件交互。如果需要使用这些服务,可以注册监听器,这会导致服务持有了Context的引用,如果在Activity销毁的时候没有注销这些监听器,会导致内存泄漏。
    public class MyActivity extends BaseActivity implements SensorEventListener {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            registerListener();
    
        }
    
        void registerListener() {
            SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
            Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ALL);
            sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_FASTEST);
        }
    
        @Override
        public void onSensorChanged(SensorEvent event) {
    
        }
    
        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {
    
        }
    }
    

    恩,就酱。

    相关文章

      网友评论

          本文标题:说说 内存泄漏

          本文链接:https://www.haomeiwen.com/subject/mynmjttx.html