Java Docker容器出现OutOfMemoryError错误

3

我正在将一个Java Spring-Boot应用程序部署为Docker容器,部署的服务器有16 GB内存。

Docker服务器版本为19.03.12,运行在Ubuntu 18.04.4 LTS上。我的Docker镜像安装了openjdk-11作为Java运行时。入口点定义如下:

ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"]

我启动容器时没有对CPU和内存进行任何限制,但是当堆空间达到8 GB时,应用程序总是会出现OutOfMemoryError。尽管系统仍有约3-4 GB的可用内存,但仍在运行其他一些容器。

为什么容器中的JVM受到了某种限制,只能使用8 GB的内存,尽管它“看到”整个16 GB?我该怎么做才能让JVM允许使用系统提供的尽可能多的内存?


尝试将-Xmx设置为大于8GB的值。只需在您的ENTRYPOINT中添加“-Xmx8G”。 - Oo.oO
1
我认为你的问题在这里已经得到了回答:https://dev59.com/1G445IYBdhLWcg3w3Nsf - Rishabh Sharma
不清楚您的应用程序是否需要使用超过8G的堆空间。您可能还希望设置-XX:+HeapDumpOnOutOfMemoryError,并查看内存使用情况。 - tgdavies
2个回答

3
您可以使用命令行开关来调整JVM可用的堆大小。例如,要设置最大堆大小为12GB,其中4GB留给操作系统和其他JVM函数,请添加命令行参数-Xmx 12G
无法告诉Java可以使用尽可能多的内存,或者与操作系统安装的内存一样多-请参见为什么(Sun)JVM有固定的内存使用上限(-Xmx)?

嘿,谢谢你的回答。我知道 -Xms 和 -Xmx JVM 选项。我希望有一种通用的方法来强制系统或 JVM 推动到系统的极限。所以现在我必须解决这个问题,在部署时自动确定系统可用的内存,以便使用所需的堆选项启动容器,因为服务器并不具备相同的资源。 - Marcel Härle
1
你不总是给容器相同的内存量吗?你可以从/sys/fs/cgroup/memory.max读取容器的内存限制。如果用户没有设置内存限制,使用awk '/^MemTotal/ {print $2}' /proc/meminfo - Joni

1
你正在假设JVM将应用程序提供给所有可用内存。事实并非如此。实际上,内存量是故意限制的 - 具体值取决于系统。您可以在这里阅读有关确定实际可用于应用程序的内存量的更多信息。
至于如何手动管理应用程序能够访问多少内存,请阅读文章。它对JVM参数进行了很好的解释。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接