java jvm 內(nèi)存溢出和內(nèi)存泄漏的區(qū)別
點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號(hào)”
優(yōu)質(zhì)文章,第一時(shí)間送達(dá)
作者 | xiaojin21cen
來(lái)源 | urlify.cn/N7FVJr
76套java從入門(mén)到精通實(shí)戰(zhàn)課程分享
1、概念的區(qū)分
內(nèi)存溢出 out of memory
是指程序在申請(qǐng)內(nèi)存時(shí),沒(méi)有足夠的內(nèi)存空間供其使用,出現(xiàn) out of memory 。
比如申請(qǐng)了一個(gè)10MB 空間, 但是當(dāng)前內(nèi)存只有5MB,那就是內(nèi)存溢出。
javadoc 對(duì) OutOfMemoryError 的解釋是, 沒(méi)有空閑內(nèi)存,垃圾收集器也無(wú)未能提供更多的內(nèi)存空間 。

內(nèi)存泄露 memory leak
是指程序運(yùn)行結(jié)束后,沒(méi)有釋放已所占用的內(nèi)存空間,一次內(nèi)存泄漏 似乎不會(huì)有大的影響,但內(nèi)存泄漏 堆積后的后果就是 內(nèi)存溢出。
1)單例模式
單例的生命周期和應(yīng)用程序是一樣長(zhǎng)的,所以單例程序中如果持有對(duì)外部對(duì)象的引用的話,那么這個(gè)外部對(duì)象是不能被回收的,則會(huì)導(dǎo)致內(nèi)存泄露的產(chǎn)生。
2)一些提供close的資源未閉導(dǎo)致內(nèi)存泄漏
數(shù)據(jù)庫(kù)連接(dataSource.getConnection() ),網(wǎng)絡(luò)連接(socket)和 IO流的連接必須在finally中 close,否則不能被回收的。
2、二者的關(guān)系:
內(nèi)存溢出就是你要的內(nèi)存空間超過(guò)了系統(tǒng)實(shí)際分配給你的空間,此時(shí)系統(tǒng)相當(dāng)于沒(méi)法滿足你的需求,就會(huì)報(bào)內(nèi)存溢出的錯(cuò)誤。
內(nèi)存溢出:一個(gè)盤(pán)子用盡各種方法只能裝4個(gè)果子,你裝了5個(gè),結(jié)果掉倒地上不能吃了。這就是溢出。比方說(shuō)棧,棧滿時(shí)再做進(jìn)棧必定產(chǎn)生空間溢出,叫上溢,棧空時(shí)再做退棧也產(chǎn)生空間溢出,稱為下溢。就是分配的內(nèi)存不足以放下數(shù)據(jù)項(xiàng)序列,稱為內(nèi)存溢出。說(shuō)白了就是我承受不了那么多,那我就報(bào)錯(cuò)。
內(nèi)存泄漏是指你向系統(tǒng)申請(qǐng)分配內(nèi)存進(jìn)行使用(new),可是使用完了以后卻不歸還(delete),結(jié)果你申請(qǐng)到的那塊內(nèi)存你自己也不能再訪問(wèn)(也許你把它的地址給弄丟了),而系統(tǒng)也不能再次將它分配給需要的程序。就相當(dāng)于你租了個(gè)帶鑰匙的柜子,你存完?yáng)|西之后把柜子鎖上之后,把鑰匙丟了或者沒(méi)有將鑰匙還回去,那么結(jié)果就是這個(gè)柜子將無(wú)法供給任何人使用,也無(wú)法被垃圾回收器回收,因?yàn)檎也坏剿娜魏涡畔ⅰ?/span>
內(nèi)存泄漏的堆積最終會(huì)導(dǎo)致內(nèi)存溢出。
3、內(nèi)存溢出的原因以及解決方法
3.1、內(nèi)存溢出的原因
引起內(nèi)存溢出的原因有很多種,小編列舉一下常見(jiàn)的有以下幾種:
內(nèi)存中加載的數(shù)據(jù)量過(guò)于龐大,如一次從數(shù)據(jù)庫(kù)取出過(guò)多數(shù)據(jù);
集合類中有對(duì)對(duì)象的引用,使用完后未清空,使得JVM不能回收;
代碼中存在死循環(huán)或循環(huán)產(chǎn)生過(guò)多重復(fù)的對(duì)象實(shí)體;
使用的第三方軟件中的BUG;
啟動(dòng)參數(shù)內(nèi)存值設(shè)定的過(guò)小 。
3.2、內(nèi)存溢出的解決方案:
第一步,修改JVM啟動(dòng)參數(shù),直接增加內(nèi)存。(-Xms、-Xmx 參數(shù)一定不要忘記加)
第二步,檢查錯(cuò)誤日志,查看 “OutOfMemory” 錯(cuò)誤前是否有其它異常或錯(cuò)誤。
第三步,對(duì)代碼進(jìn)行走查和分析,找出可能發(fā)生內(nèi)存溢出的位置。
重點(diǎn)排查以下幾點(diǎn):
1.檢查對(duì)數(shù)據(jù)庫(kù)查詢中,是否有一次獲得全部數(shù)據(jù)的查詢。
一般來(lái)說(shuō),如果一次取十萬(wàn)條記錄到內(nèi)存,就可能引起內(nèi)存溢出。
這個(gè)問(wèn)題比較隱蔽,在上線前,數(shù)據(jù)庫(kù)中數(shù)據(jù)較少,不容易出問(wèn)題,上線后,
數(shù)據(jù)庫(kù)中數(shù)據(jù)多了,一次查詢就有可能引起內(nèi)存溢出。因此對(duì)于數(shù)據(jù)庫(kù)查詢盡量采用分頁(yè)的方式查詢。
2.檢查代碼中是否有死循環(huán)或遞歸調(diào)用。
3.檢查是否有大循環(huán)重復(fù)產(chǎn)生新對(duì)象實(shí)體。
4.檢查對(duì)數(shù)據(jù)庫(kù)查詢中,是否有一次獲得全部數(shù)據(jù)的查詢。
一般來(lái)說(shuō),如果一次取十萬(wàn)條記錄到內(nèi)存,就可能引起內(nèi)存溢出。
這個(gè)問(wèn)題比較隱蔽,在上線前,數(shù)據(jù)庫(kù)中數(shù)據(jù)較少,不容易出問(wèn)題,
上線后,數(shù)據(jù)庫(kù)中數(shù)據(jù)多了,一次查詢就有可能引起內(nèi)存溢出。因此對(duì)于數(shù)據(jù)庫(kù)查詢盡量采用分頁(yè)的方式查詢。
5.檢查L(zhǎng)ist、MAP等集合對(duì)象是否有使用完后,未清除的問(wèn)題。
List、MAP等集合對(duì)象會(huì)始終存有對(duì)對(duì)象的引用,使得這些對(duì)象不能被GC回收。
第四步,使用內(nèi)存查看工具動(dòng)態(tài)查看內(nèi)存使用情況。
鋒哥最新SpringCloud分布式電商秒殺課程發(fā)布
??????
??長(zhǎng)按上方微信二維碼 2 秒
感謝點(diǎn)贊支持下哈 
