Java和Docker限制的那些事儿

本文探讨了Java在Docker环境中的内存和CPU限制问题,指出旧版Java无法识别Docker内存限制,可能导致Java进程被杀死。解决方案包括使用特定JVM标志或更新到Java 10以上版本。对于OpenJ9,目前尚需设置限制,但未来将支持类似Java的内存限制标志。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【编者的话】Java和Docker不是天然的朋友。 Docker可以设置内存和CPU限制,而Java不能自动检测到。使用Java的Xmx标识(繁琐/重复)或新的实验性JVM标识,我们可以解决这个问题。

小伙伴们有兴趣想了解内容和更多相关学习资料的请点赞收藏+评论转发+关注我,后面会有很多干货。我有一些面试题、架构、设计类资料可以说是程序员面试必备!
所有资料都整理到网盘了,需要的话欢迎下载!私信我回复【111】即可免费获取

 

虚拟化中的不匹配

Java和Docker的结合并不是完美匹配的,最初的时候离完美匹配有相当大的距离。对于初学者来说,JVM的全部设想就是,虚拟机可以让程序与底层硬件无关。

那么,把我们的Java应用打包到JVM中,然后整个再塞进Docker容器中,能给我们带来什么好处呢?大多数情况下,你只是在复制JVMs和Linux容器,除了浪费更多的内存,没任何好处。感觉这样子挺傻的。

不过,Docker可以把你的程序,设置,特定的JDK,Linux设置和应用服务器,还有其他工具打包在一起,当做一个东西。站在DevOps/Cloud的角度来看,这样一个完整的容器有着更高层次的封装。

问题一:内存

时至今日,绝大多数产品级应用仍然在使用Java 8(或者更旧的版本),而这可能会带来问题。Java 8(update 131之前的版本)跟Docker无法很好地一起工作。问题是在你的机器上,JVM的可用内存和CPU数量并不是Docker允许你使用的可用内存和CPU数量。

比如,如果你限制了你的Docker容器只能使用100MB内存,但是呢,旧版本的Java并不能识别这个限制。Java看不到这个限制。JVM会要求更多内存,而且远超这个限制。如果使用太多内存,Docker将采取行动并杀死容器内的进程!JAVA进程被干掉了,很明显,这并不是我们想要的。

为了解决这个问题,你需要给Java指定一个最大内存限制。在旧版本的Java(8u131之前),你需要在容器中通过设置-Xmx来限制堆大小。这感觉不太对,你可不想定义这些限制两次,也不太想在你的容器中来定义。

幸运的是我们现在有了更好的方式来解决这个问题。从Java 9之后(8u131+),JVM增加了如下标志:

-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap


这些标志强制JVM检查Linux的cgroup配置,Docker是通过cgroup来实现最大内存设置的。现在,如果你的应用到达了Docker设置的限制(比如500MB),JVM是可以看到这个限制的。JVM将会尝试GC操作。如果仍然超过内存限制,JVM就会做它该做的事情,抛出OutOfMemoryException。也就是说,JVM能够看到Docker的这些设置。

从Java 10之后(参考下面的测试),这些体验标志位是默认开启的,也可以使用-XX:+UseContainerSupport来使能(你可以通过设置-XX:-UseContainerSupport来禁止这些行为)。

问题二:CPU

第二个问题是类似的,但它与CPU有关。简而言之,JVM将查看硬件并检测CPU的数量。它会优化你的runtime以使用这些CPUs。但是同

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值