【Android内存泄漏】关于内存泄漏(三)
2016-06-09 23:31
453 查看
什么是内存泄漏
Android虚拟机的垃圾回收采用的是根搜索算法。GC(垃圾回收机制)会从根节点(GC Roots)开始对Heap进行遍历。到最后,部分没有直接或者间接引用到GC Roots的就是需要回收的垃圾,会被GC回收掉。而内存泄漏出现的原因就是存在了无效的引用,导致本来需要被GC回收的对象没有被回收。
在之前的博客有提到内存泄漏的部分内容,关于内存泄漏(二)
如下是常犯的错误:
假如在某个Activity中需要调用MyClass中的getInstance时,选择传入的参数是Activity的context时,则有可能发生内存泄漏的风险,当instance没有释放时,Activity会一直存在,因此造成内存泄漏。
关于Android内存泄漏,在知乎上有这么个提问:使用getApplicationContext()替代getContext()就可以避免内存泄漏吗?
关于这个问题,首先要注意一点:并不是所有的Context都可以用getApplicationContext()获取到。在Dialog中就需要Activity,不过getApplicationContext()确实在一定基础上可以减少内存泄漏。所以能用getApplicationContext的情况下尽量使用。
列举是否可使用的表格总结:
非静态内部类导致内存泄漏,例如Handler,这个时候我们应当将内部写为静态内部类,在静态内部类中使用软引用/弱引用持有外部类的实例。
(软引用和弱引用指什么呢?)
1.强引用(StrongReference):
强引用是使用最为普遍的引用,如果一个对象具有强引用,那么垃圾回收机制就绝不会回收它。如:Object ob=new Object();
Obj就是强引用。
当内存不足时,JVM即使是抛出OutofMemoryError错误,也不会轻易去回收掉强引用的对象,这个时候我们可能就需要弱化引用,让垃圾回收机制可以回收它,如: Obj=null.
2.软引用(SoftReference):
当内存足够的时候,垃圾回收机制是不会回收软引用的,但是当内存不够的时候,垃圾回收机制就会回收这些软引用,而软引用可以用来实现内存敏感度高的高速缓存。
如:
String s=new String(“Hello world”);
SoftReference str=new Softreference(s);
3.弱引用(weakReference):
弱引用对象只具有极其短暂的生命周期,在垃圾回收器扫描它所管辖的内存区域的过程中,一旦发现只具有弱引用的对象,那么不管内存是否足够,该弱引用对象都会被垃圾回收机制回收,值得注意的一点是垃圾回收线程是优先级很低的线程,所以不一定能立刻扫描到弱引用。
4.虚引用(PhantomRefrence):
虚引用不会决定对象的生命周期,虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。
这些都是Java的特性,有必要去深入理解下,内存泄漏方面能优化的地方都是值得去优化的。
在Android开发上,必须铭记一点:内存有谁申请占用,就应该由谁来释放内存。保证这一点,可以避免很多内存不释放,最终导致内存泄漏的现象。
善用WeakReference
Exception里面要释放资源
界面不可见时,停止所有动画和相关线程
少用帧间动画,真要用的时候,用SurfaceView做
异步任务队列一定要用有界队列
读SqlLite的时候请尽量不要在UI线程,虽然你这样做也不会Exception
善用LeakCanary
再次复习下GC,看看Java对垃圾回收的思想和流程:
首先要了解到,垃圾回收机制不是万能的,有人问过我,Java有了垃圾回收机制,为什么还要自己去释放资源?
其实垃圾回收机制也有不能直接自动去回收的对象,当对象和外部资源有联系时就不能立即释放资源了,例如File等。
另外需要知道:GC的运行时间是不确定的,而这就意味着你无法直接控制回收垃圾的时机,在内存不足的时候你想通过垃圾回收来释放内存,但是GC却不能立即执行。同时GC运行的阶段也会占用系统资源,那么当你想推迟GC的时间,延缓占用也是很难控制的。
Android虚拟机的垃圾回收采用的是根搜索算法。GC(垃圾回收机制)会从根节点(GC Roots)开始对Heap进行遍历。到最后,部分没有直接或者间接引用到GC Roots的就是需要回收的垃圾,会被GC回收掉。而内存泄漏出现的原因就是存在了无效的引用,导致本来需要被GC回收的对象没有被回收。
在之前的博客有提到内存泄漏的部分内容,关于内存泄漏(二)
如下是常犯的错误:
public class MyClass{ private static MyClass instance; private Context context; private MyClass(Context context){ this.context=context; } public static MyClass getIntance(Context context){ if(instance==null){ synchronized(MyClass.class){ if(instance==null){ instance=new MyClass(context); } } } return instance; } }
假如在某个Activity中需要调用MyClass中的getInstance时,选择传入的参数是Activity的context时,则有可能发生内存泄漏的风险,当instance没有释放时,Activity会一直存在,因此造成内存泄漏。
关于Android内存泄漏,在知乎上有这么个提问:使用getApplicationContext()替代getContext()就可以避免内存泄漏吗?
关于这个问题,首先要注意一点:并不是所有的Context都可以用getApplicationContext()获取到。在Dialog中就需要Activity,不过getApplicationContext()确实在一定基础上可以减少内存泄漏。所以能用getApplicationContext的情况下尽量使用。
列举是否可使用的表格总结:
非静态内部类导致内存泄漏,例如Handler,这个时候我们应当将内部写为静态内部类,在静态内部类中使用软引用/弱引用持有外部类的实例。
(软引用和弱引用指什么呢?)
1.强引用(StrongReference):
强引用是使用最为普遍的引用,如果一个对象具有强引用,那么垃圾回收机制就绝不会回收它。如:Object ob=new Object();
Obj就是强引用。
当内存不足时,JVM即使是抛出OutofMemoryError错误,也不会轻易去回收掉强引用的对象,这个时候我们可能就需要弱化引用,让垃圾回收机制可以回收它,如: Obj=null.
2.软引用(SoftReference):
当内存足够的时候,垃圾回收机制是不会回收软引用的,但是当内存不够的时候,垃圾回收机制就会回收这些软引用,而软引用可以用来实现内存敏感度高的高速缓存。
如:
String s=new String(“Hello world”);
SoftReference str=new Softreference(s);
3.弱引用(weakReference):
弱引用对象只具有极其短暂的生命周期,在垃圾回收器扫描它所管辖的内存区域的过程中,一旦发现只具有弱引用的对象,那么不管内存是否足够,该弱引用对象都会被垃圾回收机制回收,值得注意的一点是垃圾回收线程是优先级很低的线程,所以不一定能立刻扫描到弱引用。
4.虚引用(PhantomRefrence):
虚引用不会决定对象的生命周期,虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。
这些都是Java的特性,有必要去深入理解下,内存泄漏方面能优化的地方都是值得去优化的。
在Android开发上,必须铭记一点:内存有谁申请占用,就应该由谁来释放内存。保证这一点,可以避免很多内存不释放,最终导致内存泄漏的现象。
善用WeakReference
Exception里面要释放资源
界面不可见时,停止所有动画和相关线程
少用帧间动画,真要用的时候,用SurfaceView做
异步任务队列一定要用有界队列
读SqlLite的时候请尽量不要在UI线程,虽然你这样做也不会Exception
善用LeakCanary
再次复习下GC,看看Java对垃圾回收的思想和流程:
首先要了解到,垃圾回收机制不是万能的,有人问过我,Java有了垃圾回收机制,为什么还要自己去释放资源?
其实垃圾回收机制也有不能直接自动去回收的对象,当对象和外部资源有联系时就不能立即释放资源了,例如File等。
另外需要知道:GC的运行时间是不确定的,而这就意味着你无法直接控制回收垃圾的时机,在内存不足的时候你想通过垃圾回收来释放内存,但是GC却不能立即执行。同时GC运行的阶段也会占用系统资源,那么当你想推迟GC的时间,延缓占用也是很难控制的。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories