摘要:
我有一个使用akka流的Java应用程序,它使用的内存比我指定的jvm要多。下面的值是我通过JAVA_OPTS设置的。
- 最大堆大小(-Xmx)= 700 MB
- 元空间(-XX)= 250 MB
- 堆栈大小(-Xss)= 1025 kb
使用这些值并将它们代入下面的公式,可以假设应用程序将使用大约950 MB。但事实并非如此,它使用了超过1.5GB。
最大内存= [-Xmx] + [-XX:元空间大小] +线程数 * [-Xss]
**问题:**您对这一点有何看法?
应用程序概述:
此Java应用程序使用alpakka连接到pubsub并使用消息。它利用akka流的并行性,在使用的消息上执行逻辑,然后将这些消息生成到Kafka示例。请参阅下面的堆转储。注意,堆只有912.9MB,因此某些内容占用了587.1MB,内存使用量超过1.5GB
"为什么这是个问题"
此应用程序部署在kubernetes群集上,POD的内存限制指定为1.5GB。因此,当运行Java应用程序的容器占用的内存超过1.5GB时,容器将被终止并重新启动。
1条答案
按热度按时间jc3wubiy1#
简短的回答是,这些内存并不包括JVM消耗的所有内存。
例如,在堆之外,内存分配用于:
MaxMetaspaceSize
控制)-Xss
管理的堆栈...请注意,如果混合不同的并发模型,每个模型将倾向于分配自己的线程,而不一定提供共享线程的方法)根据我的经验,使用最多(pod内存限制减去1 GB)的堆通常是相当安全的,但如果您正在执行特别大的I/O等,即使在那时也很容易发生OOM。
您的JVM可能附带了对native memory tracking的支持,这至少可以说明一些非堆消耗:大多数分配往往在应用程序完全加载后不久发生,因此以高得多的资源限制运行,然后停止(例如,通过SIGTERM,有足够的时间允许它保存结果),应该可以给予您了解正在处理的内容。