Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/348.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
有没有办法在不使用时降低Java堆?_Java_Memory Management_Heap - Fatal编程技术网

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

有没有办法在不使用时降低Java堆?,java,memory-management,heap,Java,Memory Management,Heap,我目前正在开发一个Java应用程序,并致力于优化其内存使用。据我所知,我正在遵循正确垃圾收集的指导原则。然而,我的堆似乎处于其最大大小,即使它不是必需的 我的程序每小时运行一次资源密集型任务,当计算机不被人使用时。此任务使用相当大的内存块,但在任务完成后立即释放所有内存。NetBeans探查器显示内存使用情况如下所示: 我真的很想在不使用时把所有堆空间都还给操作系统。我没有理由在节目至少再过一个小时就什么都不做的情况下,把它吃光 这可能吗?谢谢 JVM不是这样工作的。你不能把它还给操作系统 正

我目前正在开发一个Java应用程序,并致力于优化其内存使用。据我所知,我正在遵循正确垃圾收集的指导原则。然而,我的堆似乎处于其最大大小,即使它不是必需的

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

我真的很想在不使用时把所有堆空间都还给操作系统。我没有理由在节目至少再过一个小时就什么都不做的情况下,把它吃光

这可能吗?谢谢

JVM不是这样工作的。你不能把它还给操作系统


正如四年前编写的一些人所指出的那样,如果您为JVM提供适当的GC设置,就可以将内存返还给操作系统

您可能可以使用
-XX:MaxHeapFreeRatio
-这是GC收缩堆之前可用堆的最大百分比(默认值70)。也许将它设置得低一点(40或50?),然后使用
System.gc()
可以让您获得所需的行为


但是,没有办法强迫这种情况发生,您可以尝试鼓励JVM这样做,但您不能在需要的时候将内存拉走。尽管上述方法可能会缩小堆,但内存不一定会直接返回操作系统(尽管在JVM的最新实现中确实如此。)

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

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


Java最好保密:-Xincgc 它确实会影响性能,但并不总是那么大。有时,这取决于你在做什么。
增量垃圾收集器将内存很好地交还给系统

简短版本:是的,你可以

长版本:

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:+useComMarkSweepGC-XX:+UseParNewGC-XX:+cmsparallerRemarkenabled-XX:cmSinitiatingOccupencyFraction=value-XX:+useCSinitingOccupency

    执行较小的收集,并且比串行GC更频繁,因此限制了应用程序的中断/停止

  • G1

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

    实验性(至少在Java1.6中):尝试确保应用程序从未停止超过1s

    范例
未经任何优化的Play Framework web应用程序的内存使用情况: 如您所见,它使用了相当多的堆空间,并且使用的空间会定期释放

在这种情况下,仅使用参数的优化是无效的。有些预定任务占用了相当多的内存。在这种情况下,在内存密集型操作之后,通过使用
CMS GC
System.GC()
相结合,可以获得最佳性能。因此,WebApp的内存使用量从1.8GB减少到了400-500MB左右

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

注意:我使用VisualVM的“执行GC”按钮来执行GC,而不是代码中的
System.GC()
,因为消耗内存的计划任务只在特定时间启动,并且VisualVM更难捕获

进一步阅读

Java 12支持使用G1GC的此功能

JEP346:立即从G1返回未使用的提交内存

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

Java13使用zgc支持此功能

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

ZGC当前不会取消提交并返回内存t