垃圾收集器 Java 应用程序未释放 POD Kubernetes 中的内存

Garbage Collector Java application does not free memory in POD Kubernetes

我的应用程序的垃圾收集器有问题,我正在使用 Kubernetes 和 BigTable 作为数据源的 GCP 环境中工作。

收到负载后,应用程序不会释放内存 space 并填满内存,直到 k8s 重新启动 POD。我使用探查器查看 JVM 的行为,这就是结果。

在“Old Gen”池中,可以看到内存已满,但它从未释放 space 并且直到重新启动并再次开始时才会填满。

在池“Eden Space”中可以看到,当它正在填充时,space 被释放并且永远不会达到限制。

这是创建 docker 映像以在 k8s 中部署它时的 JVM 配置。

java
-XX:+UnlockExperimentalVMOptions
-XX:+UseG1GC
-XX:+UseCGroupMemoryLimitForHeap
-XX:+AlwaysPreTouch
-XX:ParallelGCThreads=5
-XX:GCTimeRatio=4
-XX:MaxGCPauseMillis=100
-XX:MinHeapFreeRatio=30
-XX:MaxHeapFreeRatio=30
-Xms512m
-Xmx4608m

同样的配置应用于另一个应用程序,该应用程序进行 REST 调用并且从未像本例那样出现内存填充问题。

Java版本为1.8

感谢您的帮助。

问候。

首先,您必须确定问题的根本原因才能进一步处理。我建议您使用 -XX:+PrintGCDetails 和 -XX:+PrintGCTimeStamps 收集有关该主题的更多信息。如果您认为“Old Gen”池永远不会释放 space 的假设是正确的(老实说,从图像上看并不明显),您可能会应用一些技巧来处理它:

  • 通过-XX:MaxNewSize, -XX:NewSize, -XX:MaxOldSize, -XX:MaxOldSize 直接指定新旧gc大小,确保老年代有足够的space
  • 通过 -XX:+PrintGCDetails 和 -XX:+PrintGCTimeStamps 收集更多日志,看看是否有任何问题是由于其中一代的过度使用而发生的
  • 尝试通过 -XX:SurvivorRatio 增加幸存者 space 比率以加快老年代对象的收集