从 Java 8 迁移后 Java 11 的内存问题

Hau*_*uke 9 java memory-leaks java-service-wrapper

每个人,

几周前,我们将后台应用程序从 Oracle Java 8 更改为采用 JDK 11(热点)。在最初的几周和几个月里,我们没有注意到任何事情,但现在我们的数据中心正在等待更新。在测试系统中我们注意到存在内存问题。

我们在一台服务器上运行最多 30 个应用程序实例。每一个都与 Tanuiksoft Service Wrapper 一起运行,并根据实例分配了不同数量的 XMX 内存。

我们的服务每 10 分钟打印一次以下信息

    double total = Runtime.getRuntime().totalMemory() / 1024;
    double max = Runtime.getRuntime().maxMemory() / 1024;
    double free = Runtime.getRuntime().freeMemory() / 1024;

    int activeThreads = Thread.activeCount();
    
    logger.info("Memory: [total={0}] [max={1}] [free={2}] [active threads={3}]", //
            total, max, free, activeThreads);
Run Code Online (Sandbox Code Playgroud)

这是 Java 8 的输出,其中总内存减少。

如果我理解正确的话,totalMemory 是虚拟机让操作系统保留的内存 - 那么该内存将不再可供操作系统使用。最大内存被理解为服务包装器中的 XMX 参数。freeMemory 是totalMemory 中仍然空闲的内存。

当时的输出看起来像这样

Memory: [total=278,016] [max=466,432] [free=183,895] [active threads=33]
Memory: [total=278,016] [max=466,432] [free=176,264] [active threads=33]
Memory: [total=259,072] [max=466,432] [free=132,683] [active threads=33]
Memory: [total=259,072] [max=466,432] [free=125,653] [active threads=33]
Memory: [total=259,072] [max=466,432] [free=118,370] [active threads=33]
Run Code Online (Sandbox Code Playgroud)

可以看到总内存又被释放了。如今,Java 11 看起来像这样:

Memory: [total=451,584] [max=524,288] [free=124,309] [active threads=33]
Memory: [total=451,584] [max=524,288] [free=338,183] [active threads=33]
Run Code Online (Sandbox Code Playgroud)

为什么VM不释放内存。它已保留 451 MB,其中 340 MB 仍可用。所以再次释放内存是有意义的,不是吗?该服务在下次重新启动之前不会执行任何进一步的操作,因此内存也只会最小程度地增加和减少。直到重新启动(几个小时后),可用内存仍保持在 300 MB 左右。在 Java 8 中,我们从未见过这种情况。

由于某些服务在高峰时间需要大量内存,但所有服务同时需要大量内存的可能性很小,因此我们可以很好地接受这样一个事实:服务器上所有 XMX 值的总和始终为比物理内存大。由于 Java 11 转换,我们现在遇到了问题。

我们还在wrapper.conf中输入了以下参数:

wrapper.java.additional.1=-Xmx512m
wrapper.java.additional.2=-Xms16m
wrapper.java.additional.3=-XX:MaxPermSize=256M
wrapper.java.additional.4=-XX:GCTimeRatio=19
wrapper.java.additional.5=-XX:MinHeapFreeRatio=20
wrapper.java.additional.6=-XX:MaxHeapFreeRatio=30
wrapper.java.additional.7=-XX:-ShrinkHeapInSteps
wrapper.java.additional.8=-Xlog:gc+ergo*=info
wrapper.java.additional.9=-XX:+UseG1GC
Run Code Online (Sandbox Code Playgroud)

我们对非计算中心的客户也有同样的问题,但他们并没有注意到那么多,因为只有少数实例在运行,而且内存足够高。遗憾的是,数据中心的内存有些有限。

有谁知道我们可以在这里设置什么来释放内存?