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






