JVM启动后默认将最大使用堆大小设置为物理内存的四分之一,譬如一台普通的x86服务器配置128G内存,那么启动在容器的内启动JVM会将自己最大允许使用的堆内存调整为32G内存,如果容器启动时设置JVM只允许使用4G大小的内存,那么当JVM使用内存超过4G后,将会导致内核杀死JVM。测试代码如下:
目前创新互联已为1000+的企业提供了网站建设、域名、雅安服务器托管、网站托管、企业网站设计、蒲县网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。
- 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() );
- }
- }
- }
代码非常简单,只是通过一个死循环不停地申请内存,如果是在JAVA 8u111版本之前,直接通过docker run -m 100m限制使用100M内存的情况下,运行一段时间后直接被内核杀死。输出如下:
- # JAVA MemEat
- . . .
- free memory: 1307309488
- free memory: 1306260896
- free memory: 1305212304
- free memory: 1304163712
- free memory: 1303115120
- Killed
为了避免这种情况,可以通过“ -Xmx ”设置最大堆内存后再次运行。
- # 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由于堆内存不足,自己退出了。这种在JVM添加参数的方式有个弊端:如果修改了容器的内存限制,还需要调整启动参数。为此在JAVA 8u144版本之后添加了动态调整的功能,能够根据用户设定的内存限制动态调整,启动参数如下:
- # JAVA -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap MemEat
当我们修改了内存参数后JVM便可以随之调整。JAVA对于容器的支持不断增强到最新的JAVA 10版本后,已经原生支持容器环境,无需添加任何参数。不仅如此,新版JAVA 10还支持CPU在容器内动态调整。如下所示JVM调整内存最大堆:
- # docker run -it -m 1024M --entrypoint bash openjdk:11-jdk
- # java -XX:+PrintFlagsFinal -version | grep MaxHeapSize
- size_t MaxHeapSize = 268435456
可以看到上面的最大堆调整到内存限制的四分之一,而非物理内存的四分之一。还可以支持CPU自适应,如下所示:
- # docker run -it --CPUs 2 ---entrypoint bash openjdk:11-jdk
- jshell> Runtime.getRuntime().availableProcessors()
- $1 ==> 2
可以看到通过JAVA的API成功地获取到当前设置的CPU个数。
如果是其他编程语言希望获取到容器的CPU和内存限制,可以通过容器内的cgroup文件系统,如获取容器内存的限制:
- # cat /sys/fs/cgroup/memory/memory.limit_in_bytes
- 104857600
【编辑推荐】
本文标题:为啥Java应用迁移到容器后会出现OOM?
转载来源:http://www.gawzjz.com/qtweb/news47/198297.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联