代码之家  ›  专栏  ›  技术社区  ›  SkyBlue

Java Spring服务的内存/垃圾收集器问题

  •  1
  • SkyBlue  · 技术社区  · 1 年前

    我在使用Spring框架(3.2.1)的Java服务(21)时遇到了内存问题。

    服务比较简单。它公开了一个REST端点。

    当调用此端点时,服务会向另一个服务发出HTTP请求(使用Spring的RESTCRIENT机制)以获取数据。一旦检索到数据,就会返回。

    有很多数据,所以当我调用我的端点时,内存使用量会激增,这并不让我感到惊讶。

    然而,一旦处理完成,内存就会保持高位,永远不会下降。

    以下是VisualVM的屏幕截图:

    enter image description here

    内存保持高位,直到我在VisualVM中单击“执行GC”。我试过了,即使24小时后,即使没有人呼叫我的端点,记忆仍然很高。

    以下是更多信息:

    • 该服务在Docker容器中运行。使用的图像是3.9.5-eclips-temurin-21
    • 我尝试过调整JVM参数:
      • 无任何参数
      • -Xms128m-XX:+使用G1GC-Xmx3g
      • -Xms128m-XX:+使用G1GC-Xmx3g-XX:最大GC使用毫米=200 在这三种情况下,问题仍然存在

    你知道问题的起源和可能的解决方案吗?

    2 回复  |  直到 1 年前
        1
  •  2
  •   Stephen C    1 年前

    这是正常的行为。Java垃圾收集器旨在最小化两个指标:

    • 垃圾收集器的CPU利用率,和/或
    • 垃圾收集器运行时,“停止世界”暂停。

    最小化总体内存利用率不是主要目标。

    在您的示例中,您使用的G1GC具有(隐式或显式)最大暂停时间目标。JVM发现仍有约1GB的可用堆空间,并估计它还不需要触发GC来满足暂停时间保证。所以它不会。。。因为在没有GC的情况下运行GC 足够地 收集垃圾的效率很低。

    坦率地说,我认为这根本不是问题。但如果 平均的 内存利用率对您来说确实是一个问题,请查看 G1PeriodicGC 选项。这些命令告诉JVM定期触发GC,前提是JVM还没有(太)忙。请参阅 JEP 346 了解详情。请注意,此功能是在Java 12中实现的,因此它应该在您(我认为)使用的Java 21映像中可用。

    请注意,这将提高JVM的CPU利用率: TANSTAAFL .

        2
  •  0
  •   SkyBlue    1 年前

    感谢您的回复。我添加了G1PeriodicGC选项,它解决了我的问题。

    “坦率地说,我认为这根本不是问题” 就我而言,这是一个问题。该服务在我的服务器上毫无目的地使用了2GB的RAM。此数据不会保留在缓存中以供将来重用,因此需要删除。我意识到这一点是因为我的服务器上的RAM使用率太高,导致其他服务出现内存不足错误。

    我不是Java专家,但从技术上讲,使用垃圾回收器设置是一个好的解决方案吗? 此外,您提到它会影响CPU使用率。这是否意义重大,或者它是否具有与垃圾收集器自行运行相同的影响?