日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
為啥Java應用遷移到容器后會出現(xiàn)OOM?

JVM啟動后默認將最大使用堆大小設置為物理內存的四分之一,譬如一臺普通的x86服務器配置128G內存,那么啟動在容器的內啟動JVM會將自己最大允許使用的堆內存調整為32G內存,如果容器啟動時設置JVM只允許使用4G大小的內存,那么當JVM使用內存超過4G后,將會導致內核殺死JVM。測試代碼如下:

目前創(chuàng)新互聯(lián)已為1000+的企業(yè)提供了網(wǎng)站建設、域名、雅安服務器托管、網(wǎng)站托管、企業(yè)網(wǎng)站設計、蒲縣網(wǎng)站維護等服務,公司將堅持客戶導向、應用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。

 
 
 
  1. import JAVA.util.ArrayList; 
  2. import JAVA.util.List; 
  3.  
  4. public class MemEat { 
  5.     public static void main(String[] args) { 
  6.         List l = new ArrayList<>(); 
  7.         while (true) { 
  8.             byte b[] = new byte[1048576]; 
  9.             l.add(b); 
  10.             Runtime rt = Runtime.getRuntime(); 
  11.             System.out.println( "free memory: " + rt.freeMemory() ); 
  12.         } 
  13.     } 

代碼非常簡單,只是通過一個死循環(huán)不停地申請內存,如果是在JAVA 8u111版本之前,直接通過docker run -m 100m限制使用100M內存的情況下,運行一段時間后直接被內核殺死。輸出如下:

 
 
 
  1. # JAVA MemEat 
  2. . . . 
  3. free memory: 1307309488 
  4. free memory: 1306260896 
  5. free memory: 1305212304 
  6. free memory: 1304163712 
  7. free memory: 1303115120 
  8. Killed 

為了避免這種情況,可以通過“ -Xmx ”設置最大堆內存后再次運行。

 
 
 
  1. # JAVA -Xmx100m MemEat 
  2. . . . 
  3. free memory: 8382264 
  4. free memory: 7333672 
  5. free memory: 6285080 
  6. free memory: 5236488 
  7. Exception in thread "main" JAVA.lang.OutOfMemoryError: JAVA heap space MemEat.main(MemEat.JAVA:8) 

可以看到JVM由于堆內存不足,自己退出了。這種在JVM添加參數(shù)的方式有個弊端:如果修改了容器的內存限制,還需要調整啟動參數(shù)。為此在JAVA 8u144版本之后添加了動態(tài)調整的功能,能夠根據(jù)用戶設定的內存限制動態(tài)調整,啟動參數(shù)如下:

 
 
 
  1. # JAVA -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap MemEat 

當我們修改了內存參數(shù)后JVM便可以隨之調整。JAVA對于容器的支持不斷增強到最新的JAVA 10版本后,已經(jīng)原生支持容器環(huán)境,無需添加任何參數(shù)。不僅如此,新版JAVA 10還支持CPU在容器內動態(tài)調整。如下所示JVM調整內存最大堆:

 
 
 
  1. # docker  run -it -m 1024M --entrypoint bash openjdk:11-jdk    
  2. # java -XX:+PrintFlagsFinal -version | grep MaxHeapSize 
  3.   size_t MaxHeapSize = 268435456                

可以看到上面的最大堆調整到內存限制的四分之一,而非物理內存的四分之一。還可以支持CPU自適應,如下所示:

 
 
 
  1. # docker  run -it --CPUs 2 ---entrypoint bash openjdk:11-jdk 
  2. jshell> Runtime.getRuntime().availableProcessors() 
  3. $1 ==> 2 

可以看到通過JAVA的API成功地獲取到當前設置的CPU個數(shù)。

如果是其他編程語言希望獲取到容器的CPU和內存限制,可以通過容器內的cgroup文件系統(tǒng),如獲取容器內存的限制:

 
 
 
  1. # cat /sys/fs/cgroup/memory/memory.limit_in_bytes 
  2. 104857600 

 【編輯推薦】

  1. Java基礎與項目實戰(zhàn)之EasyUI+Maven+Shiro-SSM權限項目實戰(zhàn)
  2. 【天眼】Java大規(guī)模分布式跟蹤監(jiān)控系統(tǒng)
  3. 面試官:說說對React refs 的理解?應用場景?
  4. Java并發(fā)編程系列之一Thread簡介

本文標題:為啥Java應用遷移到容器后會出現(xiàn)OOM?
分享地址:http://www.dlmjj.cn/article/ccshheh.html