Java堆外內存及導致的溢出錯誤

     除了Java堆和永生代之外,還有一些區域會佔用較多的內存,而這些內存總和可能受到操作系統進程最大的內存限制。比如,一個服務器內存2G,其中1.6G分配給Java堆,另外的0.4G分配給操作系統和下面的區域,那麼0.4G很可能不夠用。例如當Direct Memory佔用過多的內存時,虛擬機雖然會對Direct Memory進行回收,但是卻不像新生代,老年代一樣,發現空間不足了就通知收集器進行垃圾回收,它只能等待老年代滿了後進行Full GC,然後順便幫它清理一下內存中的廢棄對象。否則,它只有等到拋出內存溢出異常後,先catch掉,再在catch塊裏大喊一聲:System.gc();若是虛擬機沒有執行,它就只有看着堆中還有很多空閒內存,而自己卻拋出內存溢出異常。例如:NIO操作需要使用到Direct Memory內存。

    1、Direct Memory:其是堆外緩存Big Memory的一個實現,它能夠在內存中序列化大批量對象,而不影響JVM垃圾回收的性能。可通過-XX:MaxDirectMemorySize調整大小,內存不足時拋出OutOfMemoryError或者OutOfMemoryError:Direct buffer memory。

    2、線程堆棧:可通過-Xss調整大小,內存不足時拋出StackOverflowError(無法分配新的棧幀)或者OutOfMemoryError:unable to create new native thread(無法建立新的線程)。

    3、Socket緩存區:每個Socket連接都Receive和Send兩個緩存區,分別佔大約37kb和25kb內存,連接多的話這塊內存佔用也比較客觀,如果無法分配,則可能會拋出IOException:Too many open files異常。

     4、JNI代碼:如果代碼中使用JNI調用本地庫,那本地庫使用的內存也不在堆中。

     5、虛擬機和GC:虛擬機和GC的代碼執行也需要一定的內存。

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