內(nèi)存泄漏:
指 程序在申請內(nèi)存后,當(dāng)該內(nèi)存不需再使用 但卻無法被釋放,歸還給程序的現(xiàn)象。
內(nèi)存溢出
是指程序在申請內(nèi)存時,沒有足夠的內(nèi)存空間供其使用,出現(xiàn)out of memory
android常見內(nèi)存泄漏
1.Handler 引起的內(nèi)存泄漏
2.單例模式引起的內(nèi)存泄漏
3.非靜態(tài)內(nèi)部類創(chuàng)建靜態(tài)實例引起的內(nèi)存泄漏
4.非靜態(tài)匿名內(nèi)部類引起的內(nèi)存泄漏
5.注冊/反注冊未成對使用引起的內(nèi)存泄漏
6.資源對象沒有關(guān)閉引起的內(nèi)存泄漏
7.集合對象沒有及時清理引起的內(nèi)存泄漏
優(yōu)化內(nèi)存泄漏
1、Handler持有的引用最好使用弱引用,在Activity被釋放的時候要記得清空Message,取消Handler對象的Runnable;
2、非靜態(tài)內(nèi)部類、非靜態(tài)匿名內(nèi)部類會自動持有外部類的引用,為避免內(nèi)存泄露,可以考慮把內(nèi)部類聲明為靜態(tài)的;
3、對于生命周期比Activity長的對象,要避免直接引用Activity的context,可以考慮使用ApplicationContext;
4、廣播接收器、EventBus等的使用過程中,注冊/反注冊應(yīng)該成對使用;
5、不再使用的資源對象Cursor、File、Bitmap等要記住正確關(guān)閉;
6、集合里面的東西、有加入就應(yīng)該對應(yīng)有相應(yīng)的刪除
如何檢測內(nèi)存泄漏
1,在Android studio3.0以前,在下邊有一個Android Monitor,在Android studio3.0以后,將其改為了Android profiler,里邊可以分析CPU使用率,內(nèi)存、包括網(wǎng)絡(luò)狀態(tài),一般檢測內(nèi)存泄漏,只需要點擊memory,然后確保移動端啟動的程序和studio工具正確連接,如果要檢測當(dāng)前頁面是否存在泄漏問題,只需要將該activity finish,然后底部有一個小垃圾桶,他是起到手動觸發(fā)gc的功能,通過手動回收,然后再去包下查看該應(yīng)用當(dāng)前存留的實例,如果剛剛finish并且gc的activity仍然存在,證明在這個activity當(dāng)中存在內(nèi)存泄漏。點擊額外生成的activity(一般是后邊帶有$這個符號),一般在studio右邊會有泄漏原因的提示,當(dāng)然具體位置還需要程序員通過經(jīng)驗判斷,主動到項目業(yè)務(wù)中查詢。
2,可以使用leakcanary框架,這個相對比較簡單,只需要添加依賴,在application啟動的時候,判斷是否有l(wèi)eakcanary對該進(jìn)程泄漏的監(jiān)聽,如果沒有,在程序啟動的時候安裝leakcanary即可
內(nèi)存溢出原因
內(nèi)存溢出就是內(nèi)存不夠,引起內(nèi)存溢出的原因有很多種,常見的有以下幾種:
1、內(nèi)存中加載的數(shù)據(jù)量過于龐大,如一次從數(shù)據(jù)庫取出過多數(shù)據(jù);
2、集合類中有對對象的引用,使用完后未清空,使得JVM不能回收;
3、代碼中存在死循環(huán)或循環(huán)產(chǎn)生過多重復(fù)的對象實體;
4、使用的第三方軟件中的BUG;
5、啟動參數(shù)內(nèi)存值設(shè)定的過?。?/p>
內(nèi)存溢出解決方法
【情況一】:
java.lang.OutOfMemoryError:Javaheapspace:
這種是java堆內(nèi)存不夠,一個原因是真不夠(如遞歸的層數(shù)太多等),另一個原因是程序中有死循環(huán);
如果是java堆內(nèi)存不夠的話,可以通過調(diào)整JVM下面的配置來解決:
-Xms3062m
-Xmx3062m</pre>
【情況二】
java.lang.OutOfMemoryError:GCoverheadlimitexceeded
【解釋】:JDK6新增錯誤類型,當(dāng)GC為釋放很小空間占用大量時間時拋出;一般是因為堆太小,導(dǎo)致異常的原因,沒有足夠的內(nèi)存。
【解決方案】:
1、查看系統(tǒng)是否有使用大內(nèi)存的代碼或死循環(huán);
2、通過添加JVM配置,來限制使用內(nèi)存:
-XX:-UseGCOverheadLimit</pre>
【情況三】:
java.lang.OutOfMemoryError:PermGenspace:
這種是P區(qū)內(nèi)存不夠,可通過調(diào)整JVM的配置:
-XX:MaxPermSize=128m
-XXermSize=128m
【注】:
JVM的Perm區(qū)主要用于存放Class和Meta信息的,Class在被Loader時就會被放到PermGenspace,這個區(qū)域成為年老代,GC在主程序運行期間不會對年老區(qū)進(jìn)行清理,
默認(rèn)是64M大小,當(dāng)程序需要加載的對象比較多時,超過64M就會報這部分內(nèi)存溢出了,需要加大內(nèi)存分配,一般128m足夠
【情況四】:
java.lang.OutOfMemoryError:Directbuffermemory
調(diào)整-XX:MaxDirectMemorySize=參數(shù),
如添加JVM配置:
-XX:MaxDirectMemorySize=128m</pre>
【情況五】:
java.lang.OutOfMemoryError:unabletocreatenewnativethread
【原因】:Stack空間不足以創(chuàng)建額外的線程,要么是創(chuàng)建的線程過多,要么是Stack空間確實小了。
【解決】:由于JVM沒有提供參數(shù)設(shè)置總的stack空間大小,但可以設(shè)置單個線程棧的大?。欢到y(tǒng)的用戶空間一共是3G,除了Text/Data/BSS/MemoryMapping幾個段之外,Heap和Stack空間的總量有限,是此消彼長的。因此遇到這個錯誤, 可以通過兩個途徑解決:
1.通過-Xss啟動參數(shù)減少單個線程棧大小,這樣便能開更多線程(當(dāng)然不能太小,太小會出現(xiàn)StackOverflowError);
2.通過-Xms-Xmx兩參數(shù)減少Heap大小,將內(nèi)存讓給Stack(前提是保證Heap空間夠用)。
【情況六】:
java.lang.StackOverflowError
【原因】:這也內(nèi)存溢出錯誤的一種,即線程棧的溢出,要么是方法調(diào)用層次(比如存在無限遞歸調(diào)用),要么是線程棧太小。
【解決】:優(yōu)化程序設(shè)計,減少方法調(diào)用層次;調(diào)整-Xss參數(shù)增加線程棧大小</pre>