Android进阶-Android的内存泄漏

参考链接

参考链接

理解Java的强引用、软引用、弱引用和虚引用

理解Java的强引用、软引用、弱引用和虚引用

java的内存: 栈区、堆区、静态区/方法区

1、栈区:由编译知器自动分配释放,存放函数的参数值、局部变量的值等、基本类型的变量,例如int a=3中的a、对象的引用变量,例如Thread t=new Thread()中的t、具体方法执行结束之后,系统自动释放JVM内存资源。

2、堆区:一般由程序员分配释放,存放由new创建的对象和数组,jvm不定时道查看这个对象,如果没有引用指向这个对象就内回收。

3、静态区/方法区:存放全局变量,静态变量和字符串常量,不释放和整个应用的生命周期一样。

堆内存和栈内存,两者的区别?

  1. 引用变量是普通变量,定义时在栈内存中分配,引用变量在程序运行到作用域外后被释放。而数组和对象本身在堆中分配,即使程序运行到使用new产生数组和对象的语句所在的代码块之外,数组和对象本身占用的堆内存也不会被释放。数组和对象在没有引用变量指向它的时候,才变成垃圾,不能再被使用,但是仍然占着内存,在随后的一个不确定的时间被垃圾回收器释放掉,这个也是Java比较占内存的主要原因。实际上,栈中的引用变量指向堆内存中的变量,这就是Java中的指针。

  2. 通俗来讲,堆是用来存放对象的,而栈是用来执行程序的。

  3. jvm只有一个堆区(heap),被所有线程共享;
    每个线程包含一个栈区(stack),每个栈中的数据都是私有的,其他的栈不能访问,但是同一个栈中变量是共享的;分为3个部分:基本类型变量区,执行环境上下文,操作指令区。

为什么要有堆和栈?这样设计有什么好处?

  1. Java自动管理堆和栈,程序员不能直接地设置栈和堆。
  2. Java的堆是一个运行时数据区。堆是由JVM的垃圾回收器自动管理的。堆的优势是可以在程序运行时,动态地分配内存
    大小,但是正是由于这个原因,它的存取速度较慢。
  3. 栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小和生存期是必须确定的,缺乏灵活性。
    栈有一个很重要的特性,就是存在栈中的数据可以共享。假设我们同时定义:

int a = 3;

int b = 3;

编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有3这个值,如果没找到,就将3存放进来,然后将a指向3。接着处理int b = 3;在创建完b的引用变量后,因为在栈中已经有3这个值,便将b直接指向3。这样,就出现了a与b同时均指向3的情况。这时,如果再令a=4;那么编译器会重新搜索栈中是否有4值,如果没有,则将4存放进来,并令a指向4;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值。要注意这种数据的共享与两个对象的引用时
指向一个对象的这种共享是不同的,因为这种情况a的修改并不会影响到b, 它是由编译器完成的,它有利于节省空间。而一个对象引用变量修改了这个对象的内部状态,会影响到另一个对象引用变量。

内存泄漏分析:

强引用

Object obj = new Object(); //只要obj还指向Object对象,Object对象就不会被回收
obj = null;  //手动置null,帮助垃圾收集器回收此对象

单例的内存泄漏

单例的内存泄露 当Android想要释放Activtity的时候 有单例(单例是static类型的 他的生命周期和整个程序一样)使用了Activity的context导致单例无法释放,推荐使用Application的Context

内部类

非静态内部类持有外部类实例的强引用。

如果我们在内部类创建一个静态的实例,该实例的生命周期和程序一样长,导致了该实例一直持有外部类的引用 导致该外部类的内存一直无法释放。

class test{
  private static final TAG = "";
}

解决方法:
1.将内部类更改为静态内部类

static class test{
  private static final TAG = "";
}

2.避免静态变量

class test{
  private final TAG = "";
}

匿名内部类

如果这个非静态内部类实例内部执行耗时任务期间,Activity不幸被销毁了,就会导致外围对象不会被回收,从而导致内存泄漏

AsyncTask

void startAsyncTask() {
    new AsyncTask<Void, Void, Void>() {
        @Override protected Void doInBackground(Void... params) {
            while(true);
        }
    }.execute();
}

解决方法

private static class NimbleTask extends AsyncTask<Void, Void, Void> {
    @Override protected Void doInBackground(Void... params) {
        while(true);
    }
}

void startAsyncTask() {
    new NimbleTask().execute();
}

Handler

Android中使用Handler造成内存泄露的分析和解决

// 容易造成内存泄漏的写法:
   private Handler mHandler = new Handler() {
       @Override
       public void handleMessage(Message msg) {
           //...刷新页面
       }
   };

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       loadData();
   }

   private void loadData() {
       //...request
       Message message = Message.obtain();
       mHandler.sendMessage(message);
   }

解决方法1: 使用静态内部类并且弱引用Activity

//    修复内存泄漏的方法:
    private MyHandler mHandler = new MyHandler(this);
    private TextView mTextView ;
    private static class MyHandler extends Handler {
        private WeakReference<Context> reference;
        public MyHandler(Context context) {
            reference = new WeakReference<>(context);
        }
        @Override
        public void handleMessage(Message msg) {
            MainActivity activity = (MainActivity) reference.get();
            if(activity != null){
//                activity.mTextView.setText("");
            }
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        loadData();
    }

    private void loadData() {
        //...request
        Message message = Message.obtain();
        mHandler.sendMessage(message);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mHandler.removeCallbacksAndMessages(null);
    }

解决方式2: 将Handler 置null

public class HandlerTestActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler_test);
    }

    public void testHandler(View view) {
        test();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mHandler.removeCallbacksAndMessages(null);
        mHandler = null;
    }

    private Message mMessage = new Message();
    private Handler mHandler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            startActivity(new Intent(HandlerTestActivity.this, TestActivity.class));
            return false;
        }
    });

    private void test() {
        new Thread(
                new Runnable() {
                    @Override
                    public void run() {
                        // Handler内存泄露测试(假象)
                        SystemClock.sleep(3000);
                        
                        mMessage.what = 3;
                        if(mHandler!=null){
                        mHandler.sendMessage(mMessage);
                        }
                    }
                }
        ).start();
    }
}

Thread

void testThread() {
   new Thread(new Runnable() {
           @Override
           public void run() {
               while (true) {
                   try {
                       Thread.sleep(1000);
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
               }
           }
       }).start();
}

解决方法

private Thread thread;

@Override
public void onDestroy() {
    super.onDestroy();
    if (thread != null) {
        thread.interrupt();
    }
}

void spawnThread() {
    thread = new Thread(new Runnable() {
           @Override
           public void run() {
               while (!isInterrupted()) {
                   try {
                       Thread.sleep(1000);
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
               }
           }
       }).start();
}

bitmap资源未释放

建议手动调用recycle()方法,释放其Native内存:

if(bitmap != null && !bitmap.isRecycled()){  
    bitmap.recycle(); 
    bitmap = null; 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值