常见内存泄漏
来源:互联网 发布:井冈山大学网络平台 编辑:程序博客网 时间:2024/04/30 21:18
Handler 内存泄漏
Handler 内部类持有 外部类Activity的引用,如果Activity退出而Handler还有延迟处理的消息没有处理完,会导致Activity不能回收,反复如此会导致内存泄露。
解决方案一: onDestroy时清除消息,mHandler.removeCallbacksAndMessages(null); // 参数为null时会清除所有消息。
解决方案二:声明Handler为static并持有Activity的弱引用。关键看程序中注释的地方
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
SystemClock.sleep(1000);
}
}
}).start();
}
Thread 是一个匿名内部类,当我们finish的时候,该activity实例不会真正销毁,GC机制也不会进行该实例的垃圾回收,因为匿名内部类和非静态内部类持有外部类的强引用,也就是说Thread持有外部activity的强引用,而thread内部while(true)是死循环,线程不会停止,对外部activity的强引用也不会消失。这样就造成了 memory leak,内存溢出。通常情况下我们可以设置一个flag,在activity,的生命周期ondestroy中改变flag的状态,但是!!!主线程和子线程的执行时有线程调度的,也就是说会造成竞争的现象,两个线程会争夺cup时间片的执行权,额。。越挖越深,这又会造成我们虽然改变的flag的状态,但是,子线程中的flag并不是马上就能改变值,因为jvm memory model,原型和执行原理,所有的线程都是在自己的工作内存中工作的,对值得操作是先从主内存读取到工作线程的工作内存中,然后cpu对工作内存的值进行修改,最后再写回主内存,所以主线程对flag的操作可能恰好的发生在子线程已经读完主内存的值到工作内存,但是还没有执行的这段时间,所以,我们应该让flag的状态改变能够让子线程马上可见,应该在声明flag的时候加上volatile关键字,虽然该关键字不能保证操作的原子性,但是能够保证变量flag的可见性。当然,还有,我们可以声明一个静态类。
慎用静态类与静态变量,比如当我们旋转屏幕,可能会造成activity的销毁与重建(虽然国内很多应用不允许旋转屏幕),不希望重新加载图片,所以,有些人会这样写:private static Drawable background;然后,这样:ImageView imageView = new ImageView(MainActivity.this);
imageView.setBackground(background);很聪明,这样无论旋转多少次屏幕,bitmap都不会重新加载了,省去了大量的时间,但是!!!imageView 引用了MainActivity的context。imageView.setBackground(background);这句源码中(父类View中)background.setCallback(this);background又引用了imageView的回调强引用,这样旋转屏幕,就会造成之前的MainActivity不能被销毁和回收,他的生命甚至和static一样长,所以,内存泄露了。记得Android官方有个经典的例子和这个很像。
- 常见内存泄漏原因
- 常见内存泄漏
- Android常见内存泄漏
- 常见的内存泄漏
- 常见内存泄漏分析
- 常见内存泄漏原因
- 常见的内存泄漏
- 一个常见的内存泄漏
- java内存泄漏常见情况
- 内存泄漏及常见解决方法
- 内存泄漏常见原因总结
- java内存泄漏常见场景
- Android 常见的内存泄漏
- android常见的内存泄漏
- 【框架-MFC】常见内存泄漏
- Android常见内存泄漏分析
- [Android]常见的内存泄漏
- android 常见的内存泄漏
- 使用Java求某点到直线上的投影点
- IOS网络测速
- 学习之路
- 微信商城开发案例
- 如何将各个文件夹下的.h文件汇总到include文件下,快捷方便的方法!
- 常见内存泄漏
- HashMap和Hashtable的区别
- sqlite3fun.c:155: first defined here execSqlite3 closeSqlite3 getSqlite3dbName编译不通过
- 在linux查看内存的大小
- 文本处理以及freetype的使用
- 计算listview上移距离,避免输入法遮挡
- Python文件处理
- Shell编程(1):变量
- [leetcode] 258. Add Digits