內(nèi)存泄漏:
指 程序在申請(qǐng)內(nèi)存后眷蜈,當(dāng)該內(nèi)存不需再使用 但卻無法被釋放,歸還給程序的現(xiàn)象怜珍。
內(nèi)存溢出
是指程序在申請(qǐng)內(nèi)存時(shí)端蛆,沒有足夠的內(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)實(shí)例引起的內(nèi)存泄漏
4.非靜態(tài)匿名內(nèi)部類引起的內(nèi)存泄漏
5.注冊(cè)/反注冊(cè)未成對(duì)使用引起的內(nèi)存泄漏
6.資源對(duì)象沒有關(guān)閉引起的內(nèi)存泄漏
7.集合對(duì)象沒有及時(shí)清理引起的內(nèi)存泄漏
優(yōu)化內(nèi)存泄漏
1酥泛、Handler持有的引用最好使用弱引用今豆,在Activity被釋放的時(shí)候要記得清空Message,取消Handler對(duì)象的Runnable柔袁;
2呆躲、非靜態(tài)內(nèi)部類、非靜態(tài)匿名內(nèi)部類會(huì)自動(dòng)持有外部類的引用捶索,為避免內(nèi)存泄露插掂,可以考慮把內(nèi)部類聲明為靜態(tài)的;
3腥例、對(duì)于生命周期比Activity長的對(duì)象辅甥,要避免直接引用Activity的context,可以考慮使用ApplicationContext燎竖;
4璃弄、廣播接收器、EventBus等的使用過程中构回,注冊(cè)/反注冊(cè)應(yīng)該成對(duì)使用夏块;
5疏咐、不再使用的資源對(duì)象Cursor、File脐供、Bitmap等要記住正確關(guān)閉浑塞;
6、集合里面的東西政己、有加入就應(yīng)該對(duì)應(yīng)有相應(yīng)的刪除
如何檢測(cè)內(nèi)存泄漏
1酌壕,在Android studio3.0以前,在下邊有一個(gè)Android Monitor,在Android studio3.0以后匹颤,將其改為了Android profiler仅孩,里邊可以分析CPU使用率托猩,內(nèi)存印蓖、包括網(wǎng)絡(luò)狀態(tài),一般檢測(cè)內(nèi)存泄漏京腥,只需要點(diǎn)擊memory赦肃,然后確保移動(dòng)端啟動(dòng)的程序和studio工具正確連接,如果要檢測(cè)當(dāng)前頁面是否存在泄漏問題公浪,只需要將該activity finish他宛,然后底部有一個(gè)小垃圾桶,他是起到手動(dòng)觸發(fā)gc的功能欠气,通過手動(dòng)回收厅各,然后再去包下查看該應(yīng)用當(dāng)前存留的實(shí)例,如果剛剛finish并且gc的activity仍然存在预柒,證明在這個(gè)activity當(dāng)中存在內(nèi)存泄漏队塘。點(diǎn)擊額外生成的activity(一般是后邊帶有$這個(gè)符號(hào)),一般在studio右邊會(huì)有泄漏原因的提示宜鸯,當(dāng)然具體位置還需要程序員通過經(jīng)驗(yàn)判斷憔古,主動(dòng)到項(xiàng)目業(yè)務(wù)中查詢。
2淋袖,可以使用leakcanary框架鸿市,這個(gè)相對(duì)比較簡單,只需要添加依賴即碗,在application啟動(dòng)的時(shí)候焰情,判斷是否有l(wèi)eakcanary對(duì)該進(jìn)程泄漏的監(jiān)聽,如果沒有剥懒,在程序啟動(dòng)的時(shí)候安裝leakcanary即可
內(nèi)存溢出原因
內(nèi)存溢出就是內(nèi)存不夠内舟,引起內(nèi)存溢出的原因有很多種,常見的有以下幾種:
1蕊肥、內(nèi)存中加載的數(shù)據(jù)量過于龐大谒获,如一次從數(shù)據(jù)庫取出過多數(shù)據(jù)蛤肌;
2、集合類中有對(duì)對(duì)象的引用批狱,使用完后未清空裸准,使得JVM不能回收;
3赔硫、代碼中存在死循環(huán)或循環(huán)產(chǎn)生過多重復(fù)的對(duì)象實(shí)體炒俱;
4、使用的第三方軟件中的BUG爪膊;
5权悟、啟動(dòng)參數(shù)內(nèi)存值設(shè)定的過小推盛;
內(nèi)存溢出解決方法
【情況一】:
java.lang.OutOfMemoryError:Javaheapspace:
這種是java堆內(nèi)存不夠峦阁,一個(gè)原因是真不夠(如遞歸的層數(shù)太多等),另一個(gè)原因是程序中有死循環(huán)耘成;
如果是java堆內(nèi)存不夠的話榔昔,可以通過調(diào)整JVM下面的配置來解決:
-Xms3062m
-Xmx3062m</pre>
【情況二】
java.lang.OutOfMemoryError:GCoverheadlimitexceeded
【解釋】:JDK6新增錯(cuò)誤類型,當(dāng)GC為釋放很小空間占用大量時(shí)間時(shí)拋出瘪菌;一般是因?yàn)槎烟∪龌幔瑢?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時(shí)就會(huì)被放到PermGenspace壁顶,這個(gè)區(qū)域成為年老代珠洗,GC在主程序運(yùn)行期間不會(huì)對(duì)年老區(qū)進(jìn)行清理,
默認(rèn)是64M大小若专,當(dāng)程序需要加載的對(duì)象比較多時(shí)许蓖,超過64M就會(huì)報(bào)這部分內(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空間確實(shí)小了米酬。
【解決】:由于JVM沒有提供參數(shù)設(shè)置總的stack空間大小,但可以設(shè)置單個(gè)線程棧的大星髀帷赃额;而系統(tǒng)的用戶空間一共是3G加派,除了Text/Data/BSS/MemoryMapping幾個(gè)段之外,Heap和Stack空間的總量有限跳芳,是此消彼長的芍锦。因此遇到這個(gè)錯(cuò)誤, 可以通過兩個(gè)途徑解決:
1.通過-Xss啟動(dòng)參數(shù)減少單個(gè)線程棧大小飞盆,這樣便能開更多線程(當(dāng)然不能太小娄琉,太小會(huì)出現(xiàn)StackOverflowError);
2.通過-Xms-Xmx兩參數(shù)減少Heap大小吓歇,將內(nèi)存讓給Stack(前提是保證Heap空間夠用)孽水。
【情況六】:
java.lang.StackOverflowError
【原因】:這也內(nèi)存溢出錯(cuò)誤的一種,即線程棧的溢出城看,要么是方法調(diào)用層次(比如存在無限遞歸調(diào)用)女气,要么是線程棧太小。
【解決】:優(yōu)化程序設(shè)計(jì)析命,減少方法調(diào)用層次主卫;調(diào)整-Xss參數(shù)增加線程棧大小</pre>