處理 Java 的“Cannot allocate memory”錯誤

今天在配置 DCA 服務器的時候,檢驗 java 版本的時候忽然遇到了一個 Cannot allocate memory 錯誤

  

[root@elcid-prod1 ~]# java -version

Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(0x00007ff55c5ea000, 4096, 0) failed; error='Cannot allocate memory' (errno=12)

#

# There is insufficient memory for the Java Runtime Environment to continue.

# Native memory allocation (mmap) failed to map 4096 bytes for committing reserved memory.

# An error report file with more information is saved as:

# /root/hs_err_pid5138.log

  

查找了一下相關文檔,發現這個錯誤的含義其實就是像它自己說的,沒法分配內存了。

 

The problem is inherent with the way Java allocates memory when executing processes. When Java executes a process, it must fork() then exec(). Forking creates a child process by duplicating the current process. By duplicating the current process, the new child process will request approximately the same amount of memory as its parent process, essentially doubling the memory required. However, this does not mean all the memory allocated will be used, as exec() is immediately called to execute the different code within the child process, freeing up this memory. As an example, when Stash tries to locate git, the Stash JVM process must be forked, approximately doubling the memory required by Stash.

 

解決方案呢有兩個,第一個是用別的方法(例如 posix_spawn)替換掉 Java 的 fork/exec 方法從而申請到內存,第二個是開啓系統的 Over-commit,跳過系統的可用內存檢查直接分配。

 

第一個方法比較麻煩,需要使用一個 custom JNI binding 去更改 Java 底層調用,所以先不嘗試。

第二個方法比較簡單,但可能會導致依賴 C 語言 malloc() 的程序出錯。

 

總之先試試第二個吧,畢竟就是改下系統變量的事兒。

臨時更改: echo 1 > /proc/sys/vm/overcommit_memory

永久更改: 編輯 /etc/sysctl.conf,修改參數 vm.overcommit_memory = 1,重啓服務器或者用戶重新登錄

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