Android 内存溢出和内存泄漏的问题
android 内存溢出和内存泄漏的问题
在面试中,经常有面试官会问“你知道什么是内存溢出?什么是内存泄漏?怎么避免?”通过这篇文章,你可以回答出来了。
内存溢出 (oom)是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如只申请了一个integer,但给它存了long才能存下的数,那就会出现内存溢出。
内存泄露 (memory leak)是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。
内存泄漏最终会导致内存溢出。
如何避免内存溢出?
强引用:强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。 当内存空间不足,java虚拟机宁愿抛出outofmemoryerror错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。
软引用:如果一个对象只具有软引用,但内存空间足够时,垃圾回收器就不会回收它;直到虚拟机报告内存不够时才会回收, 只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。 软引用可以和一个引用队列(referencequeue)联合使用,如果软引用所引用的对象被垃圾回收器回收,java虚拟机就会把这个软引用加入到与之关联的引用队列中。
弱引用:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间是否足够,都会回收它的内存。 不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。 弱引用可以和一个引用队列(referencequeue)联合使用,如果弱引用所引用的对象被垃圾回收,java虚拟机就会把这个弱引用加入到与之关联的引用队列中。
虚引用:虚引用可以理解为虚设的引用,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。 虚引用主要用来跟踪对象被垃圾回收器回收的活动。 虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (referencequeue)联合使用。 当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。 程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。 如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。
1,释放强引用,使用软引用和弱引用;
2,图像处理
大部分的oom都是发生在图片加载上的,当我们加载大图时,需要特别注意避免oom的发生。
处理大图片时,不管你的手机内存有多大,如果不对图片进行处理,都有可能会发生内存溢出问题。
1、在内存中压缩图片
装载大图片时需要对图片进行压缩,使用等比例压缩的方法直接在内存中处理图片
options options = new bitmapfactory.options(); options.insamplesize = 5; // 原图的五分之一,设置为2则为二分之一 bitmapfactory.decodefile(myimage.getabsolutepath(), options);
这样做要注意的是,图片质量会变差,insamplesize设置的值越大,图片质量就越差,不同的手机厂商缩放的比例可能不同。
2、使用完图片后回收图片所占内存
由于android外层是使用java而底层使用的是c语言在里层为图片对象分配的内存空间。
所以我们的外部虽然看起来释放了,但里层却并不一定完全释放了,我们使用完图片后最好再释放掉里层的内存空间。
if (!bitmapobject.isrecyled()) { // bitmap对象没有被回收 bitmapobject.recycle(); // 释放 system.gc(); // 提醒系统及时回收 }
3、降低要显示的图片色彩质量
android中bitmap有四种图片色彩模式:
alpha_8:每个像素需要占用内存中的1byte
rgb_565:每个像素需要占用内存中的2byte
argb_4444:每个像素需要占用内存中的2byte
argb_8888:每个像素需要占用内存中的4byte
我们创建bitmap时,默认的色彩模式是argb_8888的,这种色彩模式是质量最高的,当然这样的模式占用的内存也最大。
而argb_4444每个像素只占用2byte,所以使用argb_4444的模式也能降低图片占用的内存大小。
4、查询图片信息时不把图片加载到内存中
有时候我们取得一张图片,也许只是为了获得这个图片的一些信息,比如图片的width、height等信息,不需要显示到界面上,这个时候我们可以不把图片加载到内存中。
bitmapfactory.options options = new bitmapfactory.options(); options.injustdecodebounds = true; // 不把图片加载到内存中 bitmap btimapobject = bitmapfactory.decodefile(myimage.getabsolutepath(), options);
我们不应该把解决oom的问题寄托在争取最大的内存上,应该通过合理的代码编写来尽可能的规避oom问题。
如何避免内存泄漏?
1,在 ondestroy()方法中显示调用mthread.close();以此来结束该线程,这就避免了线程的内存泄漏问题。
2,使用application context 代替activity context;
3,资源对象没关闭造成的内存泄漏,如cursor没有close掉;
4,bitmap记得recycle掉;
5,构造adapter时,没有使用缓存的convertview。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
推荐阅读
-
Android 异步获取网络图片并处理导致内存溢出问题解决方法
-
iOS WKWebView中MessageHandler内存泄漏问题的完美解决过程
-
Android 内存溢出和内存泄漏的问题
-
解决MyEclipse下启动项目时JBoss内存溢出的问题
-
Android Studio 3.0上分析内存泄漏的原因
-
Android 5.1 WebView内存泄漏问题及快速解决方法
-
Android 异步获取网络图片并处理导致内存溢出问题解决方法
-
Android架构中添加AutoDispose解决RxJava内存泄漏问题
-
关于Yii2框架跑脚本时内存泄漏问题的分析与解决
-
Android常见的几种内存泄漏小结