内存泄漏也称作"存储渗漏",用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元。直到程序结束。(其实说白了就是该内存空间使用完毕之后未回收)即所谓内存泄漏。
内存泄漏形象的比喻是"操作系统可提供给所有进程的存储空间正在被某个进程榨干",最终结果是程序运行时间越长,占用存储空间越来越多,最终用尽全部存储空间,整个系统崩溃。所以"内存泄漏"是从操作系统的角度来看的。这里的存储空间并不是指物理内存,而是指虚拟内存大小,这个虚拟内存大小取决于磁盘交换区设定的大小。由程序申请的一块内存,如果没有任何一个指针指向它,那么这块内存就泄漏了。

while(1){malloc(1024);}这种进程

在Java中内部类的定义与使用一般为成员内部类与匿名内部类,他们的对象都会隐式持有外部类对象的引用,影响外部类对象的回收。

GC只会回收没有被引用或者根集不可到达的对象(取决于GC算法),内部类在生命周期内始终持有外部类的对象的引用,造成外部类的对象始终不满足GC的回收条件,反映在内存上就是内存泄露。(如,Android中Activity的内存泄露)

解决方案为

1.将内部类定义为static

2.用static的变量引用匿名内部类的实例

1.成员内部类

/**
  * 成员内部类
  */
 public class Outer {
     private int outer = 1;
  
     class Inner {
         public void show() {
             System.out.println("outer =" + outer);
         }
     }
  
     public static void main(String[] args) {
         Outer.Inner in = new Outer().new Inner();
         in.show();
  
     }
  
 }


 
2.方法内部类

/**
  * 方法内部类
  * 
  */
 public class Outer2 {
     private int outer = 1;
  
     public void showOut() {
  
         class Inner {
             public void show() {
                 System.out.println("outer =" + outer);
             }
         }
         new Inner().show();
     }
  
     public static void main(String[] args) {
         Outer2 in = new Outer2();
         in.showOut();
  
     }
 }


防止Handler引起内存泄漏:
方法一:通过程序逻辑进行保护:

(1)在关闭Activity时停掉对应的后台线程。线程停止就相当于切断了Handle和外部链接的线,Activity自然会在合适的时候被回收。

(2)如果Handler是被delay的Message持有了引用,那就使用Handler的removeCallbacks()方法将消息对象从消息队列移除即可。

方法二:将Handler声明为静态类,静态类不持有外部类的对象,所以Activity可以被随意回收。此处使用了弱引用WeakReference,也就是说当在内存不足时,系统会销毁弱/回收引用引用的对象,从而达到优化内存的目的。优化后代码如下:

public abstract class WeakHandler<T> extends Handler {
    protected WeakReference<T> reference;
    //创建子线程Handler使用的构造器
     public WeakHandler(Looper looper, T reference) {
         super(looper);
         this.reference = new WeakReference<>(reference);
     }    //创建主线程Handler使用的构造器
     public WeakHandler(T reference) {
         this.reference = new WeakReference<>(reference);
     }    @Override
     public void handleMessage(Message msg) {
         super.handleMessage(msg);
         T t = reference.get();
         if (t == null)
             return;
         handleMessage(t, msg);
     }    protected abstract void handleMessage(T t, Message message);
}


上述代码,我们使用了泛型,这个泛型就是我们之前说的当前类,同时提供了两种构造器,这样不管我们是创建主线程还是非主线程Handler对象时,都不会造成内存泄漏了。