有没有办法在不使用时降低Java堆?

时间:2011-02-10 01:40:01

标签: java memory-management heap

我正在研究Java应用程序,并努力优化其内存使用情况。据我所知,我正在遵循适当的垃圾收集指南。但是,似乎我的堆似乎处于最大大小,即使它不需要。

我的程序每小时运行一次资源密集型任务,此时计算机未被人使用。此任务使用了相当大的内存块,但在任务完成后立即释放所有内存。 NetBeans探查器显示内存使用情况如下所示:

Java program memory usage

我真的很想在不使用时将所有堆空间都交还给操作系统。没有理由让我把它全部占用,而程序甚至不会在至少一个小时内做任何事情。

这可能吗?感谢。

7 个答案:

答案 0 :(得分:34)

您可以使用-XX:MaxHeapFreeRatio - 这是在GC缩小之前可用的堆的最大百分比(默认为70)。也许将它设置得稍低(40或50?)然后使用System.gc()可能需要一些时间才能达到理想的行为?

没有办法强迫这种情况发生,但是你可以尝试并鼓励JVM这样做,但你不能只是随心所欲地抽出记忆。虽然上面的内容可能会缩小堆,但内存不一定会直接返回给操作系统(尽管在最近的JVM实现中它也是如此。)

答案 1 :(得分:13)

简短版:是的,你可以。

长版:

Java / JVM如何管理内存

对于大多数应用程序,JVM默认值都可以。看起来JVM希望应用程序只在有限的时间内运行。因此它似乎没有释放它自己的记忆。

为了帮助JVM决定如何以及何时执行垃圾收集,应提供以下参数:

  • -Xms指定最小堆大小
  • –Xmx指定最大堆大小

对于服务器应用程序,请添加:-server

这对我来说还不够。我想要更多的控制权!

如果上述参数不够,可以影响JVM关于垃圾收集的行为。

首先,当您认为垃圾收集有意义时,可以使用System.gc()告诉VM。第二,您可以指定JVM应使用哪些垃圾收集器:

不同种类的垃圾收集器:

  • 串行GC

    命令行参数:-XX:+UseSerialGC

    停止您的应用程序并执行GC。

  • 并行GC

    命令行参数:-XX:+UseParallelGC -XX:ParallelGCThreads=value

    与您的应用程序并行运行次要集合。减少主要馆藏所需的时间,但使用另一个帖子。

  • 并行压缩GC

    命令行参数:-XX:+UseParallelOldGC

    与您的应用程序并行运行主要馆藏。使用更多的CPU资源,减少内存使用量。

  • CMS GC

    命令行参数:-XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=value -XX:+UseCMSInitiatingOccupancyOnly

    执行较小的集合,并且比 Serial GC 更频繁,从而限制了应用程序的中断/停止。

  • <强> G1

    命令行参数:-XX:+UnlockExperimentalVMOptions -XX:+UseG1GC

    实验(至少在Java 1.6中):尝试确保应用程序永远不会停止超过1秒。

    实施例

没有任何优化的Play Framework Web应用程序的内存使用情况: Play Framework WebApp without optimizations 如您所见,它使用了相当多的堆空间,并且定期释放已用空间。

在这种情况下,仅使用参数的优化无效。有一些计划的任务使用了相当多的内存。在这种情况下,通过在内存密集型操作之后使用CMS GCSystem.gc()结合来实现最佳性能。因此,WebApp的内存使用量从1.8 GB减少到大约400-500 MB。

你可以在这里看到另一个来自VisualVM的截图,它显示了JVM如何释放内存并实际返回到操作系统:

Memory is being freed by the JVM and returned to the OS 注意:我使用VisualVM的“执行GC”按钮在我的代码中执行GC而不是System.gc(),因为消耗内存的计划任务仅在特定时间启动,而使用VisualVM更难捕获

进一步阅读

答案 2 :(得分:4)

  

JVM无法正常工作。你不能把它还给OS。

正如四年前写的几个人所指出的,如果你给JVM提供了正确的GC设置,你可以给内存回服。

答案 3 :(得分:3)

一种可能性是让您的后台java应用程序每小时启动一个外部jvm实例来运行您的任务。这样,只有原始的jvm应用程序在任务之间运行。

答案 4 :(得分:3)

如果您的应用在不活动期间处于静止状态,操作系统可能会为您换出这些页面,从而减轻他们对物理内存的压力。

http://www.linuxvox.com/2009/10/what-is-the-linux-kernel-parameter-vm-swappiness/

答案 5 :(得分:3)

Java最好保守秘密:-Xincgc 它确实会影响性能,但并不总是如此。有时它确实取决于你正在做什么。 增量垃圾收集器很好地将内存传回系统!

答案 6 :(得分:2)

Java 12 使用G1GC支持此功能。

  

JEP 346:立即从G1返回未使用的承诺内存。

     

增强G1垃圾收集器,使其在空闲时自动将Java堆内存返回到操作系统。

https://openjdk.java.net/jeps/346