![内存泄漏原因解析_第1页](http://file4.renrendoc.com/view/10dfa9f5f918dba04078dbbb51a365a2/10dfa9f5f918dba04078dbbb51a365a21.gif)
![内存泄漏原因解析_第2页](http://file4.renrendoc.com/view/10dfa9f5f918dba04078dbbb51a365a2/10dfa9f5f918dba04078dbbb51a365a22.gif)
![内存泄漏原因解析_第3页](http://file4.renrendoc.com/view/10dfa9f5f918dba04078dbbb51a365a2/10dfa9f5f918dba04078dbbb51a365a23.gif)
![内存泄漏原因解析_第4页](http://file4.renrendoc.com/view/10dfa9f5f918dba04078dbbb51a365a2/10dfa9f5f918dba04078dbbb51a365a24.gif)
![内存泄漏原因解析_第5页](http://file4.renrendoc.com/view/10dfa9f5f918dba04078dbbb51a365a2/10dfa9f5f918dba04078dbbb51a365a25.gif)
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
一、什么是内存泄漏?内存泄漏是当程序不再使用到的内存时,释放内存失败而产生了无用的内存消耗。内存泄漏并不是指物理上的内存消失,这里的内存泄漏是值由程序分配的内存但是由于程序逻辑错误而导致程序失去了对该内存的控制,使得内存浪费。二、内存泄漏检测内存信息查看:android程序内存被分为2部分:native和dalvik,dalvik就是我们平常说的java堆,我们创建的对象是在这里面分配的,而bitmap是直接在native上分配的,对于内存的限制是native+dalvik不能超过最大限制。用以下命令可以查看程序的内存使用情况:adbshelldumpsysmeminfo$package_nameor$pid//使用程序的包名或者进程id用com.tencent.qqpimsecure为例:G:XUsersXftdministrator>adbshelldumpsysmeminfocom.tencent_qqpInsecureApplicationsNemari^UsagfeCkB>:Uptime:41?Q5881Ftealtine:77394308**NENINFOinpid15446[can.tencent-qqpimsecupe]**natiuedaluikothei?totalsiae:100567175NXfi17231allocated:60103159NXfi9169Fpee:S534016NXfi4869CPss>:57745Q06779Cs:hai*eddii*t:233G187210192Cpi*ivdii*t:15&43244240G128ObjectsUieus::0UiewRoots=0AppContexts::0Octiuities=0Assets=4ftssetManaget's:4LocalBinders:=18ProxyBinders:17DeathRecipients:=0OpmSSLSockets:=0SQLheap:0MEMORY._USED:0PftGEGftGHE_OVERFLOW:0MfiLLOC._SIZE:50AssetAllocationseip:/data/app/com.tencent_(mpimsecure-l_apk:/resources_arsc:464K
具体每一项代表什么,参考:/questions/2298208/how-to-discover-memory-usage-of-my-application-in-android#2299813,我们比较关心的是这2行:naitlvedfclvikothertotfilsizs:100567175Nyfi17231ctllocaibed."3159N/A其中size是需要的内存,而allocated是分配了的内存,对应的2列分别是native和dalvik,当总数也就是total这一列超过单个程序内存的最大限制时,OOM就很有可能会出现了。多数时候,发生OOM都是在做一些跟图片相关的操作,以下提出一些建议尽量可以减少这种情况的发生:检测内存泄露的基本思想以〃GCRoofs”的对象作为起始点向下搜索,搜索形成的路径称为引用链,当一个对象到feCRoots没有任何引用链相连(即不可达的,测该对象被判定为可以被回收的对象,反之不能被回收也写出了内存泄露的原因:对象无用了,但仍然可达(未释放),垃圾回收器无法回收。三、内存泄漏有什么危害?内存泄漏对于app没有直接的危害,即使app有发生内存泄漏的情况,也不一定会引起app崩溃,但是会增加app内存的占用。内存得不到释放,慢慢的会造成app内存溢出。所以我们解决内存泄漏的目的就是防止app发生内存溢出。四、其中内存泄漏产生的实例原因:静态变量引起的内存泄漏在java中静态变量的生命周期是在类加载时开始,类卸载时结束。换句话说,在android中其生命周期是在进程启动时开始,进程死亡时结束。所以在程序的运行期间,如果进程没有被杀死,静态变量就会一直存在,不会被回收掉。如果静态变量强引用了某个Activity中变量,那么这个Activity就同样也不会被释放,即便是该Activity执行了onDestroy(不要将执行onDestroy和被回收划等号)。解决办法:寻找与该静态变量生命周期差不多的替代对象。若找不到,将强引用方式改成弱引用。在Activity被静态变量引用时,使用getApplicationContext因为Application生命周期从程序开始到结束,和static变量的一样。单例引起的Context内存泄漏publicclassIMManager{privateContextcontext;privatestaticIMManagermlnstance;publicstaticIMManagergetInstance(Contextcontext){if(mInstance==null){synchronized(IMManager.class){if(mInstance==null)mInstance=newIMManager(context);}}returnmInstance;}privateIMManager(Contextcontext){this.context=context;}}当调用getInstance时,如果传入的context是Activity的contexto只要这个单例没有被释放,这个Activity也不会被释放。解决方案传入Application的context,因为Application的context的生命周期比Activity长,可以理解为Application的context与单例的生命周期一样长,传入它是最合适的。publicclassIMManager{privateContextcontext;privatestaticIMManagermlnstance;publicstaticIMManagergetInstance(Contextcontext){if(mInstance==null){synchronized(IMManager.class){if(mInstance==null)//将传入的context转换成Application的contextmInstance=newIMManager(context.getApplicationContext());}}returnmInstance;}privateIMManager(Contextcontext){this.context=context;}}非静态内部类引起的内存泄漏在java中,创建一个非静态的内部类实例,就会引用它的外围实例。如果这个非静态内部类实例做了一些耗时的操作,就会造成外围对象不会被回收,从而导致内存泄漏。解决办法:1.将内部类变成静态内部类2.如果有强引用Activity中的属性,则将该属性的引用方式改为弱引用。因为弱引用只要GC发现了就会回收它,因此可尽快回收3.在业务允许的情况下,当Activity执行onDestory时,结束这些耗时任务。内部线程造成的内存泄漏publicclassLeakAtyextendsActivity{©OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedlnstanceState);setContentView(R.layout.aty_leak);test();}publicvoidtest(){〃匿名内部类会引用其外围实例LeakAty.this,所以会导致内存泄漏newThread(newRunnable(){©Overridepublicvoidrun(){while(true){try{Thread.sleep(1000);}catch(InterruptedExceptione){e.printStackTrace();}}}}).start();}}解决方案将非静态匿名内部类修改为静态匿名内部类publicclassLeakAtyextendsActivity{©OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedlnstanceState);setContentView(R.layout.aty_leak);test();}//加上static,变成静态匿名内部类publicstaticvoidtest(){newThread(newRunnable(){©Overridepublicvoidrun(){while(true){try{Thread.sleep(1000);catch(InterruptedExceptione){e.printStackTrace();}).start();Handler的使用造成的内存泄漏由于在Handler的使用中,handler会发送message对象到MessageQueue中然后Looper会轮询MessageQueue然后取出Message执行,但是如果一个Message长时间没被取出执行,那么由于Message中有Handler的引用,而Handler一般来说也是内部类对象,Message引用Handler,Handler引用Activity这样使得Activity无法回收。解决办法:依旧使用静态内部类+弱引用的方式可解决.publicclassLeakAtyextendsActivity{©OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedlnstanceState);setContentView(R.layout.aty_leak);fetchData();}privateHandlermHandler=newHandler(){publicvoidhandleMessage(android.os.Messagemsg){switch(msg.what){caseO://刷新数据break;default:break;}};};privatevoidfetchData(){〃获取数据mHandler.sendEmptyMessage(O);}}mHandler为匿名内部类实例,会引用外围对象LeakAty.this,如果该Handler在Activity退出时依然还有消息需要处理,那么这个Activity就不会被回收。解决方案publicclassLeakAtyextendsActivity{privateTextViewtvResult;privateMyHandlerhandler;©OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedlnstanceState);setContentView(R.layout.aty_leak);tvResult=(TextView)findViewByld(R.id.tvResult);handler=newMyHandler(this);fetchData();}//第一步,将Handler改成静态内部类。privatestaticclassMyHandlerextendsHandler{//第二步,将需要引用Activity的地方,改成弱引用。privateWeakReference<LeakAty>atylnstance;publicMyHandler(LeakAtyaty){this.atylnstance=newWeakReference<LeakAty>(aty);}©OverridepublicvoidhandleMessage(Messagemsg){super.handleMessage(msg);LeakAtyaty=atylnstance==null?null:atyInstance.get();〃如果Activity被释放回收了,则不处理这些消息if(aty==null||aty.isFinishing()){return;}aty.tvResult.setText(〃fetchdatasuccess");}}privatevoidfetchData(){//获取数据handler.sendEmptyMessage(O);}©OverrideprotectedvoidonDestroy(){//第三步,在Activity退出的时候移除回调super.onDestroy();handler.removeCallbacksAndMessages(null);}}AsyncTask造成内存泄漏packagecom.myapplication;importandroid.os.AsyncTask;importandroid.support.v7.app.AppCompatActivity;importandroid.os.Bundle;importandroid.util.Log;importandroid.view.View;publicclassActivity2extendsAppCompatActivity{©OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedlnstanceState);setContentView(R.layout.activity_2);findViewById(R.id.finish2).setOnClickListener(newView.OnClickListener()©OverridepublicvoidonClick(Viewv){finish();}});newAsyncTask<String,Integer,String>(){©OverrideprotectedStringdoInBackground(String...params){try{Thread.sleep(6000);}catch(InterruptedExceptione){}returnssss;}©OverrideprotectedvoidonPostExecute(Strings){super.onPostExecute(s);Log.d("mmmmmmactivity2”,〃〃+s);}}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,〃〃);}}为什么?上面代码在activity中创建了一个匿名类AsyncTask,匿名类和非静态内部类相同,会持有外部类对象,这里也就是activity,因此如果你在Activity里声明且实例化一个匿名的AsyncTask对象,则可能会发生内存泄漏,如果这个线程在Activity销毁后还一直在后台执行,那这个线程会继续持有这个Activity的引用从而不会被GC回收,直到线程执行完成。怎么解决?自定义静态AsyncTask类AsyncTask的周期和Activity周期保持一致。也就是在Activity生命周期结束时要将AsyncTaskcancel掉。.myapplication;importandroid.os.AsyncTask;importandroid.support.v7.app.AppCompatActivity;importandroid.os.Bundle;importandroid.view.View;publicclassAsyncTaskActivityextendsAppCompatActivity{privatestaticMyTaskmyTask;©OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedlnstanceState);setContentView(R.layout.activity_asynctask);findViewById(R.id.finish).setOnClickListener(newView.OnClickListener(){©OverridepublicvoidonClick(Viewv){finish();}});myTask=newMyTask();myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,〃〃);}privatestaticclassMyTaskextendsAsyncTask{©OverrideprotectedObjectdoInBackground(Object[]params){try{//模拟耗时操作Thread.sleep(15000);}catch(InterruptedExceptione){e.printStackTrace();}_」.…一〃〃一return;©OverrideprotectedvoidonDestroy(){super.onDestroy();//取消异步任务if(myTask!=null){;TimerTasks造成内存泄漏.myapplication;importandroid.os.Bundle;importandroid.support.v7.app.AppCompatActivity;importandroid.view.View;importjava.util.Timer;importjava.util.TimerTask;publicclassTimerActivityextendsAppCompatActivity{©OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedlnstanceState);setContentView(R.layout.activity_2);findViewById(R.id.finish2).setOnClickListener(newView.OnClickListener(){©OverridepublicvoidonClick(Viewv){finish();//开始定时任务timer();voidtimer(){newTimer().schedule(newTimerTask(){©Overridepublicvoidrun(){while(true);},1000);//1秒后启动一个任务为什么?这里内存泄漏在于Timer和TimerTask没有进行Cancel,从而导致Timer和TimerTask一直引用外部类Activity。怎么解决?在适当的时机进行CanceloTimerTask用静态内部类注意:在网上看到一些资料说,解决TimerTask内存泄漏可以使用在适当的时机进行Cancelo经过测试,证明单单使用在适当的时机进行Cancel,还是有内存泄漏的问题。所以一定要用静态内部类配合使用。.myapplication;importandroid.os.Bundle;importandroid.support.v7.app.AppCompatActivity;importandroid.util.Log;importandroid.view.View;importjava.util.Timer;importjava.util.TimerTask;publicclassTimerActivityextendsAppCompatActivity{privateTimerTasktimerTask;©OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedlnstanceState);setContentView(R.layout.activity_2);findViewById(R.id.finish2).setOnClickListener(newView.OnClickListener(){©OverridepublicvoidonClick(Viewv){finish();}});//开始定时任务timer();}voidtimer(){timerTask=newMyTimerTask();newTimer().schedule(timerTask,1000);//1秒后启动一个任务}privatestaticclassMyTimerTaskextendsTimerTask{©Overridepublicvoidrun(){while(true){Log.d("ttttttttt”,"timerTask");protectedvoidonDestroy(){
super.onDestroy();//取消定时任务if(timerTask!=null){BitMap占用过多内存在Android应用里,最耗费内存的就是图片资源。而且在android系统中,读取位图Bitmap时,分给虚拟机中的图片的堆栈大小只有8M,如果图片过多,没有及时recyclebitmap,就会出现OutOfMemory异常。所以,对于图片的内存优化,是Android应用开发中比较重要的内容。解决办法:decodebitmap的时候,尽量配置下Options,例如:inSameSizeBitmap使用完以后,调用bitmap.recycle()来释放内存如果应用是基于图片的应用,尽量采用LazyLoad和DymanicRecycledecodebitmap的时候,将decode代码trycatch出来,catchoomerror,避免程序crash,可以在catch里面做一些释放内存操作经验分享:很多开发者会习惯性的在代码中直接捕获Exceptiono但是对于OutOfMemoryError来说,这样做是捕获不到的。因为OutOfMemoryError是一种Error,而不是Exceptiono在此仅仅做一下提醒,避免写错代码而捕获不到OutOfMemoryError。资源未被及时关闭造成的内存泄漏当使用了BraodcastReceiver、Cursor、引tmap等资源时,当不需要使用时,需要及时释放掉,若没有释放,则会引起内存泄漏。解决办法:在onDestory方法中及时close即可其中还有一些关于集合对象没移除,注册的对象没反注册,代码压力的问题也可能产生内存泄漏,但是使用上述的几种解决办法一般都是可以解决的。五、内存泄漏的检查工具Heap工欲善其事必先利其器,要检测“内存泄漏”的发生,需要借助DDMS中的Heap工具及MAT工具,Heap工具用于大致分析是否存在“内存泄漏”,而MAT工具则用于分析“内存泄漏”发生在哪里。Heap工具的使用介绍LauseGCcom.qiyi.viden^sdkplaycrlawscomidouguoiETci^ezipc15193252.2com.miui.notes:remate1J74com.miui.home2143com.egand^oid,AlipayGphonc:pu5h8035io.rang.push152OBandraid.pfocess.media2411com.nniui.dduH,frvice:5tflte4Q77toni.android.setSinge.3439com,miuLsecurhycenter3824cam.tina.wffibDTffmnte3C49com.n^vfd.-ierv^ernal.prQtocok4210com.?aobao.taobdo:cheirnel迎7com.Kiaomi.mezok255-21.叫瞄爵峋岫㈣程144571279Bcom.ewample.hcydemci1562<Q]Ln席砒£3曰Cotie-jLaDisplay:(Stati7」Large:&1.D23KITypeCount1230TotalSize2CI6.D7SKBSmallest168jdataobjwt%592.063MB1667MI小哩费毒牌早ITCase■砂椭5嗥艰融曲御砌1-hyiearvay(byteg.bnDlean{])733li8.924MB24E2.419Ml斗建段厢蛔]"[]曜加疮圜fDfl陶第杵都瞒4-b/tegy(fl,floatj])B.550625.363KB24B1023KIE-hjile占丫(langQ,doublen)1,23357.555KB24E4.0DEKInon-Jsvaobject1631W52KB16E2s00BKI!■,■■■■I-M3,3Ci=-191Mof971M具体操作1.1.在Devices设备列表中,找到你所在的设备,点击你想要监控的进程。2.2.点击“UpdateHeap”按钮更新堆内存的情况。3.3.点击“Heap”视图,查看内存的情况。4.4.每次在Activity的退出和进入的时候点击“CauseGC”,手动调用GC释放应用的内存。5.5.观察dataoject那一行,每一次点击"CasueGC”的时候,观察TotalSize的值,如果该值不断增加,则说明该应用程序存在“内存泄漏”。我们先模拟一下内存泄漏,然后通过Heap工具来判断一下是否存在内存泄漏。上一段存在内存泄漏的代码:©OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedlnstanceState);setContentView(R.layout.aty_leak);testLeak();}/***测试内存泄漏的代码*/privatevoidtestLeak(){newThread(newRunnable(){©Overridepublicvoidrun(){while(true){try{Thread.sleep(1000);}catch(InterruptedExceptione){e.printStackTrace();}}}}).start();}上述的代码存在内存泄漏,newRunnable(){}是一个非静态的匿名内部类,所以它会强引用创建它的外围对象LeakAty,我们来测试一下内存泄漏的过程,开启手机的方向旋转功能,不断地旋转手机,让LeakAty不断地创建新的实例。理论上如果不存在上述泄漏的代码,之前的Activity会在onDestory之后被回收内存。而一旦存在上述泄漏的代码,新创建的Ruannale实例会一直处于运行状态,它不会被回收,而它强引用的LeakAty当然也不会被回收,所以在屏幕不断旋转,之前创建的LeakAty就不会被释放,会导致旋转n次,内存中就存在n+1个的LeakAty实例。Heap工具第一次按下CauseGC按钮的截图:101DDMS-HcyD&mo/src/cDm/eKample/hcydemo/LeaIkAtyjsva-ADTFileEditSourceRefactorNavigateSearchPrcjectRunWindow旦目pQDeTices£3Q口iiI&四伺|QDeTices£3Q口iiI&四伺|嚎驾|©|度|携|时/Namecorriimiuiicloudseirvice:state4G77865'com.miui.securitycenter38Z48&5.com.nwxfd.server,interna1.prate4210865!com.evex.pico3557865'com.xiaDmi.metok25528&5Jcom.xiaDmi.market144573&5!com.android.settmgE1C4418&Hcom.miui.^ideo10S613&D!com.tencent.mobileqq136693&4'com.miui.c1audsefivice142478SI1com.andraid.musiefx1469036Zicom.android.thememanager147268631corn.xiaomi.vip147448&?'com.xa日omi.game-centerr1476936+com.tencent.mobile-qq:web148043&4!com.and『did.packageinstaIIer148783&4!com.andraid.quicksearchbox14919860;com.miui.v/eather21^:1463&1com.example.hcydem015163362:噎TJcreads目Heap£3目AllocationTrackerNetworkStatistHeapupdateswillhappenafterevein^GCforthisclientIDHeapSizeAllocatedFree%Used#0122.441MB2.222QMB217.383KB99.O5%£TypeCountTotalSizefree461196.636KRIdata0bje-ct驾3611.031MBclassobject3,8141.038MB1-byfcearray(bjteQj,boolean|T|)6961&.922MBZ-bytearray[short。charQJ12,605B88.S05KB4-bytearray(objectf],intO.floaft|T|)5178367.891KBDisplay:Stats.7SOjOOC-15,000.Jx58B8■UI——CTa4oaot-O64ifHQ.nCO■O—SavedFilters■^3LogCst£3SearchfarAcceptsJavaregexes.Prefixwithpid.mpp.tag:dftext:toimitSavedFiltersAllmessages(nofilters)上图的dataobject的TotalSize的大小为1.031M。经过多次的旋转屏幕之后,我们再看下截图❶DDMS-HcyDem0,/Eirc/com/example/hcydemoABatcAtyjava-ADTFileEdieSourceR.efactorNavigateSearchProjectRunWindowHelplie-vicesE3食ThrealsHKe&p£S日AllocationTrader寸ffetworkStatisticsFilelie-vicesE3食ThrealsHKe&p£S日AllocationTrader寸ffetworkStatisticsFile:Ea'j&dFiltercf…-IN匚wus.media2411assicam.miui.cloude&fuice:Etate4077as5cam.miui.E&cuirityrent&,nwfd,5e«ver,internal,protc4210865!com.svox.pico395786Tcom.xiaomi.metok2552皿com.xiaomLmarket14457665!CQm.android.settings104419601com.miui.video10381060!com.tencent.mobileqq13666864com.android.musicfk14590062iccm.android.thc-meTnan-agFr147260631ccmixiaomi.Yip14744063!ccm.xiaomi.game-center14769664-ccm.tencent.mobiIrqq;web14904064!cam.android,pac^tgeinstaIler14370064!cam.android,quiclcsearchbox14919060;cam.miuLwe击her215146Q62;bm.exetmpl&.hcydemo16599006H<>就Lcgfah£3顶I目皿口翼遗I仲峪IIfflIIT『Allmessages(noFifers)hnrHeapSizeAllDcatzedFree%Used23769MB23.567MB227.344KB99.07^HeapupdateswillhappenafterGCforthisclientTypefree匚ount1.201TotalSize213.969KBSmalles-t16Bdataobject43,7&72.059MB16Bcltsssobject3.S141.036MB168B1-bytearray(bytc-Q,boolean0)7331B.924MB24B2-byteairra^(shoirtf],char[]l12,949907.773KB24B4-bytearray[objea[]into,floaO9,535S20.43®KB24BDisplay;Stats*TotalSize变成了2.059M,从1.031M到2.059M,每次调用GC的过程中dataobject的总大小没有回落,所以可以证实上面的代码确实是存在内存泄漏的问题,那么泄漏发生在哪里?答案可以通过MAT工具来分析得到。六、内存泄漏的分析工具MAT要通过MAT分析,需要提供一个.hprof文件。我们可以通过”DumpHPROFfile”按钮转存当前的堆内存信息。我们将其保存为1.hprof。GCL-■:卜XrGertCOffl.tfiLi.doUJEjM^JcwciUconi.iriLSavednliwsTlv-»idiQITaip[l]®^Lloc^tiinTraclf»T亍RWbvarL2I■.kLTfcic~aQ|DDM&-HqrDtmQrnrc^caR\ilei3fTnptj1nr^dfi-mo.i,L«ilcAJ^.j^,a-ADIgl白EditEotirc^KefHOixNduig^i»Eadnch巧陌扣口:RunWindom旦白最AJIrnps^agesIna^trrt)hniandroidproo35-rnediawm.fKwfcL&ert新nbefnal.prDL42TI-0C^ffl.FFiiJ.viddaloseiBiYi.bemMLMQbileqq1第通ecm.jrdruid.rnusidk14590comandroidthemenianagerU726com.MSCHniYip-I474Jeem.MAamLgHmvt-mlHF147&9CDfYi.b0^£imi.maljil0qqMiab14S04com.android.p占14S7Acom.ardrDid.quick-searchbax14919151*6comexample.hcydpmci165&SaI44&7IW1ccm.5voK.p1roccmiM-KmirnrtdkmrnS«mimarkrtcoM.dndrDid.u'rbRqfH-vjfs-EshIgiwdFrn%Lk.dObjBClHS.7fl9Mm235fi7227.344小99J07%HeapL<jdab«回IhappenaltiCount1"Totallbize213.959KBWmslE160Large■或BUEKBMedian知Btaw-ageiazb4a,?972.019MEiiam必EM244B3.B741.DSSMBwea4Z3T5KBICiHBZB3B733T&3-241MB2da241?MB1£u62643-5KB112,545907.773«E24m17.010KBSrQB71BB.535•52045B[<B243IfiOSSKB知&74Bdmobjectclacf口与e'-b^eIbgU,booL-^nQ.!Z-bj^ie百做《如口、5占dllLb加ewCi,fioatli导出的l.hprof的格式需要通过..\sdk\tools\目录下的hprof-conv.exe工具进行转换才能被MAT成功导入,我们将其转换成outl.hprof(hprof-convE:\1.hprofE:\out1.hprof)SBC:\WIIMDOW£\&ystem22\cmd.exe—□XMicrosoftWindows[版本10.0.10240]Cc>2015MicrosoftCoi*ponation_A11Fightsreserued.C:MJsei'sMlLimnjjCa=LyLimn>d:D二\>cdD=\findroidxSoftXadt-Jjundle-wlndows—x86_64-2B131030Xsdk\tooIsD-XAndi'oidVJSoft\adt—bundle—windows—xHt_G4—20131020Vcdk\toaIs>hpi*o£—conuC-VJUsei'sMiuangCalyuanXDesktoDXp1^存泄彳届:日、*_斤Xl.iwrofG:XUsersMiuangCaiyuanMiesktoDXF^I存泄漏分析XuuLl」w『ufD:XAndvoidlXSaft:\a.d.1z—bundle—uindniws—xS6_64—20131030\sd.l<Kt:niniIs将outl.hprof导入到MAT工具中,File->OpenHeapDump…EH祢白MamarpAfid^iar□XFiatEdH史indu顽HalpMAT工具主界面一、Histogram(直方图)可列出每一个类的实例数。支持正则表达式查找,也可以计算出该类所有对象的retainedsize。默认是通过class(groupbyclass)分类展示的。EH祢白MamarpAfid^iar□XFiatEdH史indu顽Halp二、DominatorTree(支配树)DominatorTree是对象之间dominator关系树。如果从GCRoot到达Y的的所有path都经过X,那么我们称XdominatesY,或者X是Y的DominatorDominatorTree由系统中复杂的对象图计算而来。从MAT的dominatortree中可以看到占用内存最大的对象以及每个对象的dominator。我们也可以右键选择ImmediateDominator”来查看某个对象的dominator。它可以将所有对象按照Heap大小排序显示,这样大内存对象就是排在前几名的,我们可以搜索大内存对象通向GCRoots的路径,因为内存占用越高的对象越值得怀疑,使用方法跟Histogram(直方图)差不多,在这里我就不做过多的介绍了。点击左边的标签Overview,Actions->Histogram(直方图)目E<lipc.aMofYiaryAn^lyz«r£dk检MgHelp旧[Insp^ctDr蹈g目E<lipc.aMofYiaryAn^lyz«r£dk检MgHelp旧[Insp^ctDr蹈gzutLhpruf球1M%•.01虹▼路TqIClvcryXvr'■■'臻dv^BLdt^rafKift口r#.dip5em丽iG.Tk:fcarirsAttributes|ClassHie-rarchy|ValueTJWNagvalueRentiielderRep^rlf,5-tep即Step■ListsnuHibei'ofiniLincesperd-as^「TLSlIFJlWIrWT^t帅湖口函"可andwhatthey&cwpalive.T。-Ccf沁的ws:PnrnihemoB4»^函四sbjefti^oupedby匚La足ardbypaclugeiDu糖Ee匚扇*3;Delictrlaswiloodedbyrr'iu^tiple-d■虽k)dder-fi.Le■占k:GLrtnz枝indixiesl»k-SLrspe:^and占,y%t«niowrviwT白白《Eziq凸lidraporti;foi1,camporuentsbiggerthan1percentoftheictalheap.I2cifnixi<im住口口rl.Ardhyztobbrhngw』cerwisn«Wtpadloader.国N-atMSS0MavigimHntor^127WT241IM。在Histogram界面中,可列出每一个类的实例数,如我们想要知道Activity是否泄漏了,所以输入关键词Activity,然后按下回车键。fj.Eclipse-MemoryAnalyzierFibEditWindow回InspectorKfj.Eclipse-MemoryAnalyzierFibEditWindow回InspectorK$5cs|AttributesClassHierarchy|ValueTyp®NniTra-ValwiBorgec^pE?rnsrtapiisus-perls.——匚1日wNameObj4±t!□<<He...鼠mSnmdH..„*fNumflrii^Numeric^^Numeric*=android....fl24®androidim116B3二5.752口android.11-04>=i£oe&android.c.196a・2.77&&androidm.164>-W2@android.132>=32®android....132136•android.132>=1.J44&android....1z43&androidim124»=1.560蜜android.124®Hndroidi,,,V16n=IBQandmid116>=1i6&on^roidnu11&]尊&androidiu.116w=某◎android....1ia>=ie®androidim1163-=IS口android.116>=16IIIHittogram魇耳.hprof舌Ncln腾t-Nfi.ti•rTJflMoF|241h1:之后便可以得到Activity的相关的搜索结果,下图的搜索结果中Activity的实例有7个。点击选中下图标红色框框的地方,右键->MergeShortestPathstoGCRoots->excludeallphantom/weak/softetc.references。排除虚引用、弱引用、软引用的实例,剩下的都是强引用实例。EclipseMerrier^AralyrerFileEdrtWindowH^lpE,Intptrter於@Dx41719b30屋ActWhySlFFand^oidappMclassjfl^eJang.Clflss®0x416盹1Mjav^ilang.Obj^d:Iljava.Iang.dassLadder楚OxDil_l0(sbjillowlize):L_。(retainedsrze-J□GCroot:SystemClassS4aiicsAttributes-ClassHierarchyValueTypeNameValue4,1®aut1Jipiraf贸i趋钮相■尊r|Q|囹iOverview禺dfffaull_repDrtorg.Klips-E-.maLapi^uspectsl|l|HistogramS3Cla-s^Name-ObjectsLhmllowHe...341.^ACtivityZ<ISlLjmpric=-<Numerk>RrtainedH_=Numerk»「・andmid.app.AdivivyJl7111Z、,母■l?=112jOandraid.contefrt.pni.Actwrtylrrfo196Oendnmd.epp.ActivilyThreacilAppBindDeta1i640endrffid.app.Actiyil^ThreadSProuiderClimtRe.,.1i32•android.app.ActiyitylhreadJProviderRefCounl132>=2.776>=四2>=430andrcidispp-Activit^ThreadSAppIicadonllriTE-ad1=■=136•andrcidiBpp.AEtivit^ThreadtH132n=1,544Oandroid.app.ArtviSyThreadJProfller1240andrcid.app.1Ajcwri^Manager^C^rftentPrcvid...1240andraid.spp.Art'irttyManagprNatiwS11169endrcHd,spp.Acti¥il>Threadi11i16O9ndrffid.8pp.ActiMilyThrefldSGc.idl&r1i16■-=24>=1.560»=幕=16=16®BndrcidiBpp.Activit^ThrsadiProviderLKey116=■=160andrcidiapp.Activit^ThreadiDrDpBQ%Fi.epDrter116Oandroid.^pp.ActivitylWlanagH'PrDMy1Ifi3android.app.ActivifiyThreadJ2116>=16*=16函Nm”S3%■inprioriita"■■■从过滤出来的强引用的列表中,我们可以看到这七个实例都是被Thread所引用了。所以证实上面的代码确实存在内存泄漏。还有其他菜单供选择Listobjectswith(以DominatorTree的方式查看)incomingreferences引用到该对象的对象outcomingreferences被该对象引用的对象Showobjectsbyclass(以class的方式查看)incomingreferences引用到该对象的对象outcomingreferences被该对象引用的对象EclipseMemoryAnBlyzerFileEdkWindowHelp叵屈将由叫堂Cla-&sName1Dtferviert涡defauhtreportorg.eclip^e.mat.api:suspectsIIIHistogram^Regex>merge&hort&stpafihs,[selecticRe4.Ohje-ct%£&llewH■chJumeric*^NurntiFcom©Ox4Zd50oZOThresd-ISHThreadcomexsimple.hrydemo.Leak^iytl©Ox42dZ&B30Thread-IE!2Threadcom-examplp.hcydemo.Leak^tytl。Ox如Thre&d-120&Tlireaclcom.exaimple.hrydemo.Leak^iyt.1©0x42d04clDThre
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025-2030全球丙二醛行业调研及趋势分析报告
- 2025年全球及中国低空洞焊膏行业头部企业市场占有率及排名调研报告
- 2025办公写字楼出租合同范本2
- 活牛购销合同
- 广场商铺租赁合同
- 2025北京市非居民供热采暖合同(合同版本)
- 文化传播项目合同
- 门窗安装工承包合同范本
- 提升跨部门协作能力的技能培训
- 合同协议框架性合作协议
- 幼儿平衡车训练课程设计
- 创业计划路演-美甲
- 梁山伯与祝英台小提琴谱乐谱
- 我国全科医生培训模式
- 机构编制重要事项的报告范文(5篇)
- DBJ51-T 188-2022 预拌流态固化土工程应用技术标准
- 《长津湖》电影赏析PPT
- 多维阅读第10级 who is who 看看都是谁
- 滑雪运动介绍
- 高二下学期英语阅读限时训练(一)
- 半导体制造工艺-13薄膜沉积(下)综述课件
评论
0/150
提交评论