這是本系列的第六篇文章, 相關文章列表:
- OutOfMemoryError系列(1): Java heap space
- OutOfMemoryError系列(2): GC overhead limit exceeded
- OutOfMemoryError系列(3): Permgen space
- OutOfMemoryError系列(4): Metaspace
- OutOfMemoryError系列(5): Unable to create new native thread
JVM啓動參數指定了最大內存限制。如 -Xmx
以及相關的其他啓動參數. 假若JVM使用的內存總量超過可用的物理內存, 操作系統就會用到虛擬內存。
錯誤信息 java.lang.OutOfMemoryError: Out of swap space? 表明, 交換空間(swap space,虛擬內存) 不足,是由於物理內存和交換空間都不足所以導致內存分配失敗。
原因分析
如果 native heap 內存耗盡, 內存分配時, JVM 就會拋出 java.lang.OutOfmemoryError: Out of swap space? 錯誤消息, 這個消息告訴用戶, 請求分配內存的操作失敗了。
Java進程使用了虛擬內存纔會發生這個錯誤。 對 Java的垃圾收集 來說這是很難應付的場景。即使現代的 GC算法 很先進, 但虛擬內存交換引發的系統延遲, 會讓 GC暫停時間 膨脹到令人難以容忍的地步。
通常是操作系統層面的原因導致 java.lang.OutOfMemoryError: Out of swap space? 問題, 例如:
- 操作系統的交換空間太小。
- 機器上的某個進程耗光了所有的內存資源。
當然也可能是應用程序的本地內存泄漏(native leak)引起的, 例如, 某個程序/庫不斷地申請本地內存,卻不進行釋放。
解決方案
這個問題有多種解決辦法。
第一種, 也是最簡單的方法, 增加虛擬內存(swap space) 的大小. 各操作系統的設置方法不太一樣, 比如Linux,可以使用下面的命令設置:
swapoff -a
dd if=/dev/zero of=swapfile bs=1024 count=655360
mkswap swapfile
swapon swapfile
其中創建了一個大小爲 640MB 的 swapfile(交換文件) 並啓用該文件。
因爲垃圾收集器需要清理整個內存空間, 所以虛擬內存對 Java GC 來說是難以忍受的。存在內存交換時, 執行 垃圾收集 的 暫停時間 會增加上百倍,甚至更多, 所以最好不要增加虛擬內存。
如果程序允許環境還受到 “壞鄰居效應” 的干擾, 那麼JVM還要和其他程序競爭計算資源, 提高性能的辦法就是單獨部署到專用的服務器/虛擬機中。
大多數時候, 我們唯一能做的就是升級服務器配置, 增加物理機的內存。當然也可以進行程序優化, 降低內存空間的使用量, 通過堆轉儲分析器可以檢測到哪些方法/代碼分配了大量的內存。
原文鏈接: https://plumbr.eu/outofmemoryerror/out-of-swap-space
翻譯日期: 2017年9月27日