十一:堆外內存導致的溢出錯誤

問題導入:

某項目運行在內存4GB的32位Windows機器上,運行Jetty服務器,劃分了1.6GBA給堆內存,但是依舊不時會拋出內存溢出異常

 

原因:

操作系統對每個進程能管理的內存是有限制的,這臺服務器使用的32 位 Windows平臺的限制是2GB,其中劃了16GB給Java堆,而 Direct Memory內存並不算入1.6GB的堆之內,因此它最大也只能在剩餘的0.4GB空間中分出一部分。在此應用中導致溢出的關鍵是:垃圾收集進行時,虛擬機雖然會對 Direct Memory進行回收,但是 Direct Memory卻不能像新生代、老年代那樣,發現空間不足了就通知收集器進行垃圾回收,它 只能等待老年代滿了後FuGC,然後“順便地”幫它清理掉內存的廢棄對象。

否則它只能一直等到拋出內存溢出異常時,先 catch掉,再在catch塊裏面“大喊”一聲:“ System gc()!”。要是虛擬機還是不聽(譬如打開了XX:+ DisableExplicitGC開關),那就只能眼睜睜地看着堆中還有許多空閒內存,自已卻不得不拋出內存溢出異常了。而本案例中使用的CometD框架正好有大量的NIO操作需要使用到堆外直接內存(Direct Memory)

 

附加:

除了堆內存外,還會佔用較大內存的區域有:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章