新聞中心
JVM啟動(dòng)后默認(rèn)將最大使用堆大小設(shè)置為物理內(nèi)存的四分之一,譬如一臺(tái)普通的x86服務(wù)器配置128G內(nèi)存,那么啟動(dòng)在容器的內(nèi)啟動(dòng)JVM會(huì)將自己最大允許使用的堆內(nèi)存調(diào)整為32G內(nèi)存,如果容器啟動(dòng)時(shí)設(shè)置JVM只允許使用4G大小的內(nèi)存,那么當(dāng)JVM使用內(nèi)存超過4G后,將會(huì)導(dǎo)致內(nèi)核殺死JVM。測(cè)試代碼如下:

目前創(chuàng)新互聯(lián)已為1000+的企業(yè)提供了網(wǎng)站建設(shè)、域名、雅安服務(wù)器托管、網(wǎng)站托管、企業(yè)網(wǎng)站設(shè)計(jì)、蒲縣網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。
- import JAVA.util.ArrayList;
- import JAVA.util.List;
- public class MemEat {
- public static void main(String[] args) {
- List l = new ArrayList<>();
- while (true) {
- byte b[] = new byte[1048576];
- l.add(b);
- Runtime rt = Runtime.getRuntime();
- System.out.println( "free memory: " + rt.freeMemory() );
- }
- }
- }
代碼非常簡(jiǎn)單,只是通過一個(gè)死循環(huán)不停地申請(qǐng)內(nèi)存,如果是在JAVA 8u111版本之前,直接通過docker run -m 100m限制使用100M內(nèi)存的情況下,運(yùn)行一段時(shí)間后直接被內(nèi)核殺死。輸出如下:
- # JAVA MemEat
- . . .
- free memory: 1307309488
- free memory: 1306260896
- free memory: 1305212304
- free memory: 1304163712
- free memory: 1303115120
- Killed
為了避免這種情況,可以通過“ -Xmx ”設(shè)置最大堆內(nèi)存后再次運(yùn)行。
- # JAVA -Xmx100m MemEat
- . . .
- free memory: 8382264
- free memory: 7333672
- free memory: 6285080
- free memory: 5236488
- Exception in thread "main" JAVA.lang.OutOfMemoryError: JAVA heap space MemEat.main(MemEat.JAVA:8)
可以看到JVM由于堆內(nèi)存不足,自己退出了。這種在JVM添加參數(shù)的方式有個(gè)弊端:如果修改了容器的內(nèi)存限制,還需要調(diào)整啟動(dòng)參數(shù)。為此在JAVA 8u144版本之后添加了動(dòng)態(tài)調(diào)整的功能,能夠根據(jù)用戶設(shè)定的內(nèi)存限制動(dòng)態(tài)調(diào)整,啟動(dòng)參數(shù)如下:
- # JAVA -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap MemEat
當(dāng)我們修改了內(nèi)存參數(shù)后JVM便可以隨之調(diào)整。JAVA對(duì)于容器的支持不斷增強(qiáng)到最新的JAVA 10版本后,已經(jīng)原生支持容器環(huán)境,無需添加任何參數(shù)。不僅如此,新版JAVA 10還支持CPU在容器內(nèi)動(dòng)態(tài)調(diào)整。如下所示JVM調(diào)整內(nèi)存最大堆:
- # docker run -it -m 1024M --entrypoint bash openjdk:11-jdk
- # java -XX:+PrintFlagsFinal -version | grep MaxHeapSize
- size_t MaxHeapSize = 268435456
可以看到上面的最大堆調(diào)整到內(nèi)存限制的四分之一,而非物理內(nèi)存的四分之一。還可以支持CPU自適應(yīng),如下所示:
- # docker run -it --CPUs 2 ---entrypoint bash openjdk:11-jdk
- jshell> Runtime.getRuntime().availableProcessors()
- $1 ==> 2
可以看到通過JAVA的API成功地獲取到當(dāng)前設(shè)置的CPU個(gè)數(shù)。
如果是其他編程語言希望獲取到容器的CPU和內(nèi)存限制,可以通過容器內(nèi)的cgroup文件系統(tǒng),如獲取容器內(nèi)存的限制:
- # cat /sys/fs/cgroup/memory/memory.limit_in_bytes
- 104857600
【編輯推薦】
- Java基礎(chǔ)與項(xiàng)目實(shí)戰(zhàn)之EasyUI+Maven+Shiro-SSM權(quán)限項(xiàng)目實(shí)戰(zhàn)
- 【天眼】Java大規(guī)模分布式跟蹤監(jiān)控系統(tǒng)
- 面試官:說說對(duì)React refs 的理解?應(yīng)用場(chǎng)景?
- Java并發(fā)編程系列之一Thread簡(jiǎn)介
本文題目:為啥Java應(yīng)用遷移到容器后會(huì)出現(xiàn)OOM?
URL網(wǎng)址:http://m.5511xx.com/article/ccshheh.html


咨詢
建站咨詢
