天天看點

OutOfMemoryError系列(6): Out of swap space?

JVM啟動參數指定了最大記憶體限制。如 ​

​-Xmx​

​ 以及相關的其他啟動參數. 假若JVM使用的記憶體總量超過可用的實體記憶體, 作業系統就會用到虛拟記憶體。

OutOfMemoryError系列(6): Out of swap space?

錯誤資訊 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​​