最容易引發(fā)內(nèi)存溢出的,就是系統(tǒng)創(chuàng)建出來(lái)的對(duì)象!
1 對(duì)象在Eden區(qū)分配
系統(tǒng)運(yùn)行時(shí),一直不停創(chuàng)建對(duì)象,然后大量對(duì)象會(huì)填滿Eden。?Eden滿,就會(huì)觸發(fā)一次YGC,然后存活對(duì)象進(jìn)入S區(qū):
2 高并發(fā)場(chǎng)景導(dǎo)致YGC后,存活對(duì)象太多
高并發(fā)場(chǎng)景,導(dǎo)致YGC后很多請(qǐng)求還沒處理完,存活對(duì)象太多,可能就在S區(qū)放不下,只能進(jìn)入Old,Old很快就會(huì)滿了:
一旦Old放滿,就會(huì)觸發(fā)Full GC。
假設(shè)YGC后,有一批存活對(duì)象,S放不下,就等著要進(jìn)入Old,然后Old也滿,就得等Old進(jìn)行CMS GC,必須回收掉一批對(duì)象,才能讓年輕代里存活的一批對(duì)象進(jìn)去。
但Old GC后,依然存活下很多對(duì)象,這時(shí)若年輕代還有一批對(duì)象等著進(jìn)Old,可Old空間還是不足,咋辦? 只能內(nèi)存溢出!?
所以這時(shí),Old都已滿,你還要往里面放東西,而且觸發(fā)Full GC回收了Old還是沒足夠內(nèi)存空間,你卻還要放, 那只能給你個(gè)內(nèi)存溢出!JVM崩潰。
3 何時(shí)發(fā)生堆內(nèi)存溢出?
有限的內(nèi)存中放了過多的對(duì)象,而且大多數(shù)都是存活的,此時(shí)即使GC過后還是大部分都存活,所以要繼續(xù)放入更多對(duì)象已經(jīng)不可能了,此時(shí)只能引發(fā)內(nèi)存溢出。
發(fā)生內(nèi)存溢出的主要場(chǎng)景:
- 系統(tǒng)承載高并發(fā)請(qǐng)求,因請(qǐng)求量過大,導(dǎo)致大量對(duì)象都存活,所以要繼續(xù)放入新對(duì)象,實(shí)在不行了,就會(huì)引發(fā)OOM
- 系統(tǒng)有內(nèi)存泄露,即莫名其妙弄了很多對(duì)象,結(jié)果對(duì)象都存活,沒有及時(shí)取消對(duì)他們的引用,導(dǎo)致觸發(fā)GC還是無(wú)法回收,也只能引發(fā)內(nèi)存溢出
綜上,一般引發(fā)OOM,要不然是系統(tǒng)負(fù)載過高,要不然就是有內(nèi)存泄露。
4 總結(jié)
堆內(nèi)存OOM的根本原因,即對(duì)象太多,且都是存活的,即使GC過后還是沒有空間了,此時(shí)放不下新的對(duì)象,JVM只能選擇崩潰!