內(nèi)存泄漏(memory leak)
是指程序在申請內(nèi)存后,無法釋放已申請的內(nèi)存空間,一次內(nèi)存泄漏似乎不會有大的影響,但內(nèi)存泄漏堆積后的后果就是內(nèi)存溢出绞幌。
內(nèi)存溢出(out of memory )
指程序申請內(nèi)存時,沒有足夠的內(nèi)存供申請者使用一忱,或者說莲蜘,給了你一塊存儲int類型數(shù)據(jù)的存儲空間,但是你卻存儲long類型的數(shù)據(jù)帘营,那么結(jié)果就是內(nèi)存不夠用票渠,此時就會報錯OOM,即所謂的內(nèi)存溢出。
內(nèi)存泄漏的分類
-
常發(fā)性內(nèi)存泄漏:
發(fā)生內(nèi)存泄漏的代碼會被多次執(zhí)行到芬迄,每次被執(zhí)行的時候都會導致一塊內(nèi)存泄漏问顷。 -
偶發(fā)性內(nèi)存泄漏:
發(fā)生內(nèi)存泄漏的代碼只有在某些特定環(huán)境或操作過程下才會發(fā)生。 -
一次性內(nèi)存泄漏:
發(fā)生內(nèi)存泄漏的代碼只會被執(zhí)行一次禀梳,或者由于算法上的缺陷杜窄,導致總會有一塊僅且一塊內(nèi)存發(fā)生泄漏。 -
隱式內(nèi)存泄漏:
程序在運行過程中不停的分配內(nèi)存算途,但是直到結(jié)束的時候才釋放內(nèi)存塞耕。嚴格的說這里并沒有發(fā)生內(nèi)存泄漏,因為最終程序釋放了所有申請的內(nèi)存郊艘。但是對于一個服務器程序荷科,需要運行幾天唯咬,幾周甚至幾個月纱注,不及時釋放內(nèi)存也可能導致最終耗盡系統(tǒng)的所有內(nèi)存。所以胆胰,我們稱這類內(nèi)存泄漏為隱式內(nèi)存泄漏狞贱。
常發(fā)性和偶發(fā)性是相對的。對于特定的環(huán)境蜀涨,偶發(fā)性的也許就變成了常發(fā)性的瞎嬉。所以測試環(huán)境和測試方法對檢測內(nèi)存泄漏至關(guān)重要蝎毡。
內(nèi)存溢出原因
- 內(nèi)存中加載的數(shù)據(jù)量過于龐大,如一次從數(shù)據(jù)庫取出過多數(shù)據(jù)氧枣;
- 集合類中有對對象的引用沐兵,使用完后未清空,使得JVM不能回收便监;
- 代碼中存在死循環(huán)或循環(huán)產(chǎn)生過多重復的對象實體扎谎;
- 使用的第三方軟件中的BUG;
- 啟動參數(shù)內(nèi)存值設(shè)定的過小
內(nèi)存溢出的解決方案:
- 第一步烧董,修改JVM啟動參數(shù)毁靶,直接增加內(nèi)存。(-Xms逊移,-Xmx參數(shù)一定不要忘記加预吆。)
- 第二步,檢查錯誤日志胳泉,查看“OutOfMemory”錯誤前是否有其 它異彻詹妫或錯誤。
- 第三步胶背,對代碼進行走查和分析巷嚣,找出可能發(fā)生內(nèi)存溢出的位置。
1.檢查對數(shù)據(jù)庫查詢中钳吟,是否有一次獲得全部數(shù)據(jù)的查詢廷粒。一般來說,如果一次取十萬條記錄到內(nèi)存红且,就可能引起內(nèi)存溢出坝茎。這個問題比較隱蔽,在上線前暇番,數(shù)據(jù)庫中數(shù)據(jù)較少嗤放,不容易出問題,上線后壁酬,數(shù)據(jù)庫中數(shù)據(jù)多了次酌,一次查詢就有可能引起內(nèi)存溢出。因此對于數(shù)據(jù)庫查詢盡量采用分頁的方式查詢舆乔。
2.檢查代碼中是否有死循環(huán)或遞歸調(diào)用岳服。
3.檢查是否有大循環(huán)重復產(chǎn)生新對象實體。
4.檢查List希俩、MAP等集合對象是否有使用完后吊宋,未清除的問題。List颜武、MAP等集合對象會始終存有對對象的引用璃搜,使得這些對象不能被GC回收拖吼。
- 第四步,使用內(nèi)存查看工具動態(tài)查看內(nèi)存使用情況