Java JVM释放未使用的堆

Java JVM释放未使用的堆,java,spring-boot,jvm,Java,Spring Boot,Jvm,我有一个Springboot应用程序,其中Mule作为微服务在docker容器中运行。即使在空闲状态下,也需要大约700MB。注意,JVM分配了380MB的堆,这是使用-Xmx参数提供的最大堆。虽然分配了最大堆,但微服务在空闲时仅使用大约50MB。问题是如何从JVM释放回未使用的内存 似乎降低MaxHeapFreeRatio可以让JVM在有更多空闲内存时收缩。然而MinHeapFreeRatio=20-XX:MaxHeapFreeRatio=40并没有太大区别,JVM也并没有释放内存。但当我将-

我有一个Springboot应用程序,其中Mule作为微服务在docker容器中运行。即使在空闲状态下,也需要大约700MB。注意,JVM分配了380MB的堆,这是使用
-Xmx
参数提供的最大堆。虽然分配了最大堆,但微服务在空闲时仅使用大约50MB。问题是如何从JVM释放回未使用的内存

似乎降低MaxHeapFreeRatio可以让JVM在有更多空闲内存时收缩。然而
MinHeapFreeRatio=20-XX:MaxHeapFreeRatio=40
并没有太大区别,JVM也并没有释放内存。但当我将
-Xmn
与上述两个参数一起使用时,JVM会像预期的那样释放堆内存。有关示例场景,请参见下图

Java版本8

  • 为什么MinHeapFreeRatio和MaxHeapFreeRatio不能按预期工作
  • 如果上述参数正常,
    -Xmn
    的后果是什么?其值应该是多少
  • 为了实现从JVM释放内存的任务,还有哪些其他解决方案

  • 首先,这应该是一个评论,但它很可能会变得很大。问自己是否真的想将内存从JVM释放回操作系统。重新获取它会很昂贵,比如可能比按原样运行应用程序更昂贵—这会降低您的速度

    那么,java-8下的默认收集器是
    Parallel GC
    ,我不太确定那些
    MinHeapFreeRatio
    MaxHeapFreeRatio
    是否真的可以使用它。我试过使用
    G1GC
    ——确实如此,但没有使用
    Parallel
    。然后添加
    -Xmn
    可能只是运气/好时机;好吧,它不应该影响其他两个参数。这是一个相当有趣的答案,你有一个类似的问题

    为了实现从JVM释放内存的任务,还有哪些其他解决方案

    不知道你是否试过。它有一个调优机制来检测JVM何时空闲,并将空闲内存释放回操作系统。这是关于空闲调谐特性的讨论

    您可以从中获取OpenJDK-OpenJ9二进制文件


    如果您坚持使用OpenJDK热点组合,您可以尝试探索
    -XX:-ShrinkHeapInSteps
    选项,该选项有望大幅收缩堆,但我不确定它使用的是哪种GC策略。

    如果您担心几MB,那么您真的不应该使用java,尤其是mule。你应该考虑使用GO。Java不太适合这种类型的问题——它是可以做到的,但它需要大量的努力,而且在实践中结果往往令人失望。这不仅仅是“几MB”。许多Java应用程序都有这样一种模式:在其生命周期中的某段时间,它们需要一个大的内存峰值来完成一个可能是几GB的大任务,然后它们就再也不会使用那么多内存,而且由于内存从未释放到操作系统中,这是一种巨大的浪费。
    -Xmn100M  -XX:+PrintGCDetails  -XX:MinHeapFreeRatio=20 -XX:MaxHeapFreeRatio=40 -Xmx384M