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

joc*_*ull 51 java heap memory-management

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

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

Java程序内存使用情况

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

这可能吗?谢谢.

Mic*_*rry 35

您也许可以玩-XX:MaxHeapFreeRatio- 这是在GC缩小之前可用的堆的最大百分比(默认值为70).也许设置它稍低(40或50?)然后使用System.gc()可能需要一些长度来获得所需的行为?

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

  • @andersoj:此设置_does_将RAM返回给操作系统.有关一个令人印象深刻的例子,请参见http://stopcoding.wordpress.com/2010/04/12/more-on-the-incredible-shrinking-jvm-heap. (11认同)
  • 另一篇非常有趣的文章,显示`SerialGC`和`ParNewGC`回馈内存:http://www.stefankrause.net/wp/?p = 14 (5认同)
  • @andersoj请注意这个答案,因为berry120是引入该特定参数的人. (2认同)

Pea*_*nut 14

简短版:是的,你可以.

长版:

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

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

  • G1

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

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

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

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

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

内存正由JVM释放并返回到操作系统 注意:我使用VisualVM的"执行GC"按钮来执行GC而不是System.gc()我的代码,因为消耗内存的计划任务仅在特定时间启动,而使用VisualVM更难捕获.

进一步阅读


Heu*_*kos 5

Java 12使用 G1GC 支持此功能。

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

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

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

Java 13使用 zgc 支持此功能

JEP 351:ZGC:取消提交未使用的内存

ZGC 当前不会取消提交并将内存返回给操作系统,即使该内存已长期未使用也是如此。此行为并非对于所有类型的应用程序和环境都是最佳的,尤其是那些关注内存占用的应用程序和环境。例如:资源按使用付费的容器环境。

  • 应用程序可能长时间空闲并与许多其他应用程序共享或竞争资源的环境。

  • 应用程序在执行期间可能有非常不同的堆空间要求。例如,启动期间所需的堆可能大于稍后稳定状态执行期间所需的堆。

http://openjdk.java.net/jeps/351