作業系統何時分配jvm堆

作業系統何時分配jvm堆

我們的 SAP 系統之一(PI ABAP+JAVA 堆疊)出現了效能問題。為機器配置的整個 64GB 都被佔用了(還有 8 個核心)。每個人都懷疑java部分,但我認為不同。

java 伺服器節點重新啟動時出現記憶體不足錯誤。查看 hprof 文件,我發現當為伺服器節點配置 3GB(-Xms 和 Xmx)堆時,它們的大小只有 1.2G(3 個伺服器節點的平均值)。這一觀察導致以下疑問。

我讀到,當Xms和Xmx設定為相同的值時,jvm在啟動時會分配整個堆。如果是這種情況,伺服器節點從一開始就會有 3GB 的堆。如果是這樣,為什麼它沒有反映在 hprof 檔案中,或者如果 hprof 僅包含運行時分配給物件的內存,則大小清楚地表明堆內存是空閒的(超過 50%),那麼 OOM 錯誤是如何發生的。 ..!

我還知道Linux 會做一些稱為記憶體過度使用的事情。也就是說,記憶體並不是請求時實際給出的,而是在實際使用時給出的。這是否會導致記憶體不足異常。就像當 JVM 啟動時,作業系統會告訴它您已分配了 3GB 內存,但實際上將其推遲到實際需要時才分配。當jvm實際嘗試將記憶體分配給物件時,其他一些應用程式可能已經耗盡了記憶體。這可能嗎...?

即使java節點有記憶體洩漏問題,它也不會被限制在3GB堆中。它怎麼能霸佔整個64G物理記憶體......?

我觀察到的另一件事是交換空間只使用了 50%。

關於這個的任何線索...!

答案1

SAP OSS 也在調查這個問題。今天我收到了他們的回覆。我的觀察是正確的。 Java 並不是罪魁禍首。 ABAP 堆疊面臨一些問題並且沒有釋放記憶體。重新啟動ABAP工作進程後,內存在作業系統層級被釋放。

但我也想了解問題的突出部分,例如是否會發生這種情況,從而導致 JAVA OOM 錯誤...??..!!。這方面的任何資訊都會有所幫助。

答案2

Linux 上預設以啟發式模式啟用過量使用。這意味著核心通常會允許過度使用 - 這意味著將向所有請求它的進程承諾比它實際可以提供的內存更多的內存,希望進程永遠不會同時開始使用所有內存。也許您的伺服器上禁用了過度使用,您可以透過執行以下命令來檢查它:

$ cat /proc/sys/vm/overcommit_memory

如果值為 0,則開啟啟發式過量使用。

如果發生實際記憶體使用量超過系統可以提供的 RAM 量的情況,核心將啟動 OOM Killer,它會嘗試殺死進程以釋放記憶體。它通常會殺死消耗大量 RAM 的最年輕的進程,但您不能依賴它。它可能(並且將會)造成嚴重破壞。您可以透過調整 /proc//oom_adj 來修改 OOM 的親和力以殺死特定進程(例如,如果您想避免 OOM 殺死資料庫或其他一些大 RAM [ab]用戶的情況)。

因此,如果您的系統進入 OOM 階段,Java 進程的後果可能是它們立即被終止 - 這不會讓您在您觀察到的 Java 日誌中看到「記憶體不足」訊息。

將 Xmx 和 Xms 設為相同的值將阻止堆大小調整,但這並不意味著 java 進程將在啟動時立即開始使用所有記憶體。它會根據需要分配盡可能多的 VIRT 內存,但駐留資料集不會增長到 Xms,而是會根據需要保持盡可能低的水平。

就虛擬記憶體而言:核心將向java進程承諾(過量使用)它所要求的數量(Xmx +一些額外的),但所有這些記憶體不會立即分配。僅分配目前資料所需的量,您可以透過觀察駐留集大小(任務已使用的非交換實體記憶體)來了解多少。若要查看 VIRT 和 RSS 大小,您可以執行以下命令:

$ ps aux | egrep '(^USER|java)'
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
tomcat   10229 21.5  9.1 6813688 548344 ?      Sl   09:01   1:10 ....java...

您觀察到的錯誤很可能表示在 java 虛擬機器進程下執行的程式缺少堆空間。嘗試增加 Xmx 設定並重新測試您的應用程式。

相關內容