Cannot allocate memory 的分析及解決方法


Cannot allocate memory 的分析及解決方法

問題

業務方使用Python虛擬的子進程和主進程共享內存,主進程啟動后,啟動子進程時報錯"Cannot allocate memory"

問題分析

可能的原因:

  • 系統的物理RAM或交換空間不足
  • 進程在啟用CompressedOops的情況下運行,Java堆可能會阻止本機堆的增長

可能的解決方案:

  • 減少系統內存負載
  • 增加物理內存或交換空間
  • 檢查交換備份存儲是否已滿
  • 減小Java堆大小(-Xmx/-Xms)
  • 減少Java線程數
  • 減少Java線程堆棧大小(-Xss)
  • 使用-XX:ReservedCodeCacheSize設置更大的代碼緩存=
  • JVM運行的是無標度的壓縮Oops模式,其中Java堆是
  • 放在第一個4GB地址空間。Java堆基址是
  • 本機堆增長的最大限制。請使用-XX:HeapBaseMinAddress
  • 設置Java堆基並將Java堆放置在4GB虛擬地址之上

咋一看是懷疑內存不足,但從監控來看,內存還有很多富裕

進程

看到提供的可能的解決方案中有需要減少java線程數,聯想到服務器的進程數是不是滿了,首先查看服務器最大進程數 sysctl kernel.pid_max
接着一查看進程數ps -eLf | wc –l,16149遠遠還沒到32768啊,那肯定也不是進程數滿了的原因,排除。

內核參數overcommit_memory

Linux下有個內核參數overcommit_memory,是內存分配策略,程序在啟動的時候會先去申請內存,盡管不一定都會用的到那么多。
overcommit_memory此參數決定是否接受超大內存請求的條件。這個參數有三個可能的值:

  • 0 — 默認設置。內核執行啟發式內存過量使用處理,方法是估算可用內存量,並拒絕明顯無效的請求。遺憾的是因為內存是使用啟發式而非准確算法計算進行部署,這個設置有時可能會造成系統中的可用內存超載。
  • 1 — 內核執行無內存過量使用處理。使用這個設置會增大內存超載的可能性,但也可以增強大量使用內存任務的性能。
  • 2 — 內存拒絕等於或者大於總可用 swap 大小以及overcommit_ratio指定的物理RAM比例的內存請求。如果您希望減小內存過度使用的風險,這個設置就是最好的。
    目前的內存申請和可用情況cat /proc/meminfo | grep Commit
  • CommitLimit 表示系統可申請的總內存
  • Committed_AS為當前已經申請的內存

理解下什么是Overcommit和OOM:

Linux對大部分申請內存的請求都回復"yes",以便能跑更多更大的程序。因為申請內存后,並不會馬上使用內存。這種技術叫做Overcommit。當linux發現內存不足時,會發生OOM killer(OOM=out-of-memory)。它會選擇殺死一些進程(用戶態進程,不是內核線程),以便釋放內存。

當oom-killer發生時,linux會選擇殺死哪些進程?選擇進程的函數是oom_badness函數(在mm/oom_kill.c中),該函數會計算每個進程的點數(0~1000)。點數越高,這個進程越有可能被殺死。每個進程的點數跟oom_score_adj有關,而且oom_score_adj可以被設置(-1000最低,1000最高)。

解決方法

有三種方式修改內核參數,但要有root權限:

  1. 編輯/etc/sysctl.conf ,改vm.overcommit_memory=1,然后sysctl -p使配置文件生效
  2. sysctl vm.overcommit_memory=1
  3. echo 1 > /proc/sys/vm/overcommit_memory,然后sysctl –p永久生效


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM