




下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Android之内存溢出和内存泄漏的原因和解决方案基础JAVA是在JVM所虚拟出的内存环境中运行的,内存分为三个区:堆、栈和方法区。栈(stack):是简单的数据结构,程序运行时系统自动分配,使用完毕后自动释放。优点:速度快。堆(heap):用于存放由new创建的对象和数组。在堆中分配的内存,一方面由java虚拟机自动垃圾回收器来管理,另一方面还需要程序员提供修养,防止内存泄露问题。方法区(method):又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量。概念内存溢出(OutofMemory):系统会给每个APP分配内存也就是HeapSize值。当APP占用的内存加上我们申请的内存资源超虚拟机的最大内存时就会抛出的OutOfMemory异常。内存泄漏(MemoryLeak):当一个对象不在使用了,本应该被垃圾回收器(JVM)回收。但是这个对象由于被其他正在使用的有,造成无法被回收的结果。内存泄漏最终会导致内存溢出。内存抖动:内存抖动是指在短时间内有大量的对象被创建或者被回收的现象,主要是循环中大量创建、回收对象。这种情况应当尽量避免。它们三者的重要等级分别:内存溢出>内存泄露>内存抖动。内存溢出对我们的App来说,影响是非常大的。有可能导致程序闪退,无响应等现象,因此,我们一定要优先解决OOM的问题。强引用:强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。软引用:如果一个对象只具有软引用,但内存空间足够时,垃圾回收器就不会回收它;直到虚拟机报告内存不够时才会回收,只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。弱引用:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间是否足够,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。虚引用:虚引用可以理解为虚设的引用,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。关系内存泄漏是造成应用程序OOM的主要原因之一。由于Android系统为每个应用程序分配的内存有限,当一个应用中产生的内存泄漏比较多时,就难免会导致应用所需要的内存超过这个系统分配的内存限额,这就造成了内存溢出而导致应用Crash。我们的App多次出现内存泄露,可能就会导致内存溢出。但是,我们的App出现内存溢出,不一定就是因为内存泄露,因为本身Android系统分配给每一个的App的空间就是那么一点。另外,内存泄露也不一定就会出现内存溢出,因为还是泄露的速度比较慢,系统将进程杀死了,也就不会内存溢出。不过,发现内存泄露,我们还是要第一时间解决。危害内存溢出:会触发Java.Iang.OutOfMemoryError,造成程序崩溃。内存泄漏:过多的内存泄漏会造成内存溢出,同样也会造成相关UI的卡顿现象。判断是否有内存泄露的工具LeackCanaryMemoryMonitorDDMS处理方式汇总强引用,软引用和弱引用释放强引用,使用软引用和弱引用;大量的图片、音频、视频处理,当在内存比较低的系统上也容易造成内存溢出建议使用第三方,或者JNI来进行处理;Bitmap对象的处理不要在主线程中处理图片使用Bitmap对象要用recycle释放//Bitmap对象没有被回收if(!bitmapObject.isRecyled()){//释放bitmapObject.recycle();//提醒系统及时回收System.gc();}控制图片的大小,压缩大图,高效处理,加载合适属性的图片。当我们有些场景是可以显示缩略图的时候,就不要调用网络请求加载大图,例如在RecyclerView中,我们在上下滑动的时候,就不要去调用网络请求,当监听到滑动结束的时候,才去加载大图,以免上下滑动的时候产生卡顿现象。非静态内部类和匿名內部类Handler、Thread、Runnable等由于持有外部类Activity的引用,从而关闭activity,线程未完成造成内存泄漏在Activity中创建非静态内部类,非静态内部类会持有Activity的隐式引用,若内部类生命周期长于Activity,会导致Activity实收。(屏幕旋转后会重新创建Activity实例,如果内部类持有引用,将会导致旋转前的实例无法被回收)。如果一定要使用内部类,就改用static内部类,在内部类中通过WeakReference的方式引用外界资源。对Handler、Thread、Runnable等使用弱引用,并且调用removeCallbacksAndMessages等移除。举例:在下面这段代码中存在一个非静态的匿名类对象Thread,会隐式持有一个外部类的引用MainActivity。同理,若是这个Thread作为MainActivity的内部类而不是匿名内部类,他同样会持有外部类的引用。publicclassMainActivityextendsAppCompatActivity{@OverrideprotectedvoidonCreate(BundlesavedlnstanceState){super.onCreate(savedlnstanceState);setContentView(R.layout.main);leakFun();}privatevoidleakFun(){newThread(newRunnable(){@Overridepublicvoidrun(){try{Thread.sleep(10*1000);}catch(InterruptedExceptione){e.printStackTrace();}}});}}R;束:jj於薯於於孟jjj;束g芟工嚨吏於薯捞於薯实jj:直在线程休眠的这10s内,会一直隐式持有外部类的引用MainActivity,如果在10s之前,销毁MainActivity,就会报内存泄漏。同理,若是这个Thread作为MainActivity的内部类而不是匿名内部类,也会内存泄漏。总而言之:如果Activity在销毁之前,任务还未完成,那么将导致Activity的内存资源无法回收,造成内存泄漏。解决办法:在这里只需要将为Thread匿名类定义成静态的内部类即可(静态的内部类不会持有外部类的一个隐式引用)。或保证在Activity在销毁之前,完成任务!在关闭Activity的时候停掉你的后台线程。线程停掉了,就相当于切断了Handler和夕卜部连接的线,Activity自然会在合适的时候被回收。资源未及时关闭造成的内存泄漏对于使用了BraodcastReceiver,Contentobserver,Cursor,File,Stream,ContentProvider,Bitmap,动画,1/0,数据库,网络的连接等资源的使用,应该在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,造成内存泄漏。广播BraodcastReceiver:记得注销注册unregisterReceiver();文件流File:记得关闭流Inputstream/OutputStream.close();数据库游标Cursor:使用后关闭游标cursor.close();对于图片资源Bitmap:当它不再被使用时,应调用recycle()回收此对象的像素所占用的内存,再赋为null动画:属性动画或循环动画,在Activity退出时需要停止动画。在属性动画中有一类无限循环动画,如果在Activity中播放这类动画并且在onDestroy中没有去停止动画,那么这个动画将会一直播放下去,这时候Activity会被View所持有,从而导致Activity无法被释放。在Activity中onDestroy去调用objectAnimator.cancel()来停止动画。publicclassLeakActivityextendsAppCompatActivity{privateTextViewtextView;@OverrideprotectedvoidonCreate(BundlesavedlnstanceState){super.onCreate(savedlnstanceState);setContentView(R」ayout.activity_leak);textView=(TextView)findViewByld(R.id.text_view);ObjectAnimatorobjectAnimator=ObjectAnimator.ofFloat(textView,"rotation",0,360);objectAnimator.setRepeatCount(ValueAnimator.lNFINITE);objectAnimator.start();}}集合对象及时清理,使得JVM回收:我们通常会把对象存入集合中,当不使用时,清空集合,让相关对象不再被引用;objectList.clear();objectList=null;注销监听器在onPause()/onDestroy()方法中解除监听器,包括在Android自己的Listener,LocationService或DisplayManager写的Listener。static关键字修饰的变量由于生命周期过长,容易造成内存泄漏static对象的生命周期过长,应该谨慎使用。一定要使用要及时进行null处理。静态变量Activity和View会导致内存泄漏。例如:context,textView实例的生命周期与应用的生命周期一样,而他们都持有当前Activity的(MainActivity)引用,一旦MainActivity销毁,而他的引用一直被持有,就不会被回收。所以,内存泄漏就产出了。publicclassMainActivityextendsAppCompatActivity{privatestaticContextcontext;privatestaticTextViewtextView;@OverrideprotectedvoidonCreate(BundlesavedlnstanceState){super.onCreate(savedlnstanceState);setContentView(R.layout.activity_main);context=this;textView=newTextView(this);}}如果使用Context,尽可能使用Applicaiton的Context单例模式造成的内存泄漏,如context的使用,单例中传入的是activity的context,在关闭activity时,activity的内存无法持有activity的引用。在context的使用上,应该传入application的context到单例模式中,这样就保证了单例的生命周期跟application的生命周期一样。因为单例的静态特性使得单例的生命周期和应用的生命周期一样长,这就说明了如果一个对象已经不需要使用了,而单例对象还持有该对象的引用,那么这个对象将不能被正常回收,这就导致了内存泄漏。单例模式应该尽量少持有生命周期不同的外部对象,一旦持有该对象的时候,必须在该对象的生命周期结束前nullpublicclassTestManager{privatestaticTestManagerinstance;privateContextcontext;privateTestManager(Contextcontext){this.context=context;}publicstaticTestManagergetlnstance(Contextcontext){if(instance!=null){instance=newTestManager(context);}returninstance;这是一个普通的单例模式,当创建这个单例的时候,由于需要传入一个Context,所以这个Context的生命周期的长短至关重要:1、传入的是Application的Context:这将没有任何问题,因为单例的生命周期和Application的一样长;2、传入的是Activity的Context:当这个Context所对应的Activity退出时,由于该Context和Activity的生命周期一样长(Activity间接继承于Context),所以当前Activity退出时它的内存并不会被回收,因为单例对象持有该Activity的引用。所以正确的单例应该修改为下面这种方式:publicclassTestManager{privatestaticTestManagerinstance;privateContextcontext;privateTestManager(C
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 电铲初级工练习题(附参考答案)
- 2025员工拒绝签订劳动合同企业应对策略全解析
- 商业信息咨询和辅导服务协议规定事项
- 智能硬件产品设计与制造合同协议
- 知识产权转让合同协议书要求专业版
- 设备采购合同协议条款
- 经济师专业试题及答案
- 2025湖南省低空经济发展集团有限公司招聘12人(第二次)笔试参考题库附带答案详解
- 2025江西南昌市信阳鼎信产业投资集团有限公司及所属二级公司招聘24人笔试参考题库附带答案详解
- 2025广西旅发大健康产业集团有限公司招聘278人笔试参考题库附带答案详解
- 肺癌的手术治疗方案
- 藏毛窦患者护理查房
- 高温后超高性能混凝土力学性能研究
- 金属冶炼负责人安管人员培训
- 2025年中考数学总复习《四边形的证明题》专项测试卷(附答案)
- 踝关节骨折中医护理方案
- 家具鉴赏知到智慧树章节测试课后答案2024年秋东北林业大学
- 统编版语文七年级下第18课《井冈翠竹》公开课一等奖创新教学设计
- 《高等教育心理学》讲义
- 2025年汽车转向桥总成行业深度研究分析报告
- 《招生话术技巧》课件
评论
0/150
提交评论