JVM释放未使用的堆空间。

4

我有一个Springboot应用程序,其中内置了一个名为Mule的微服务,作为docker容器运行。即使处于空闲状态,它也需要大约700MB的内存。注意到JVM已经分配了380 MB的堆内存,这是使用-Xmx参数提供的最大堆,但是当微服务处于空闲状态时,它只使用了约50MB的内存。问题是如何释放JVM未使用的内存。

似乎通过减少MaxHeapFreeRatio,我们可以要求JVM在有更多自由内存比率时进行收缩。然而,MinHeapFreeRatio=20 -XX:MaxHeapFreeRatio=40并没有产生太大的差异,JVM也没有释放内存。但当我使用上述两个参数的-Xmn时,JVM如预期地释放堆内存。请参见下面的图像示例。

Java版本8

-Xmn100M  -XX:+PrintGCDetails  -XX:MinHeapFreeRatio=20 -XX:MaxHeapFreeRatio=40 -Xmx384M

enter image description here

  1. 为什么 MinHeapFreeRatio 和 MaxHeapFreeRatio 的效果与预期不符?
  2. 如果上述参数设置正确,那么 -Xmn 参数的后果是什么,它应该设置为多少?
  3. 除了通过 JVM 释放内存之外,还有哪些其他解决方案可以实现此任务?

这是一个非常有价值的问题,我也分享同感。这不仅仅是“几MB”的问题。许多Java应用程序都有一个模式,在它们的生命周期中的某个时刻,它们需要大量内存来处理一个大型任务,可能会达到数GB,然后它们再也不会使用那么多的内存了,由于内存没有释放给操作系统,这是一种巨大的浪费。 - Chin
2个回答

3

首先,这应该是一条注释,但它可能会太大了。如果您真的想要将JVM中的内存释放回操作系统,请仔细考虑。重新获取内存将是昂贵的,可能比运行您的应用程序本身更昂贵 - 这将使您变慢。

然后,在java-8下,您的默认收集器是Parallel GC,我不是非常确定那些MinHeapFreeRatioMaxHeapFreeRatio实际上是否与其配合使用。我尝试过G1GC - 它可以,但在Parallel中没有成功。然后添加-Xmn可能只是运气/好时机;据我所知,它不应影响另外两个参数。这篇文章是一个类似问题的相当有趣的答案。


不,它不会更昂贵,事实上恰恰相反。想象一下,你有一个使用几GB内存的进程(考虑到Java有多么贪婪),现在你分叉该进程并分配了另外几GB内存。过了一段时间,其中很多都被处理掉了,但由于从操作系统的角度来看仍然被分配,最终你会耗尽内存并开始分页,这些I/O将比重新分配内存花费更多。 - E.T

0
有什么其他解决方案可以实现从JVM释放内存的任务吗?
不确定您是否尝试过OpenJ9。它具有调整机制,可以检测JVM何时处于空闲状态,并将空闲内存释放回操作系统。这篇文章讨论了空闲调整功能。
您可以从adoptopenjdk获取OpenJDK-OpenJ9二进制文件。
如果您坚持使用OpenJDK-Hotspot组合,则可以尝试探索–XX:-ShrinkHeapInSteps选项,该选项预计会大幅缩小堆,但我不确定它适用于哪些GC策略。

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