我目前正在研究Java应用程序并努力优化其内存使用.据我所知,我正在遵循适当的垃圾收集指南.但是,即使不需要,我的堆似乎仍然处于最大大小.
我的程序每小时运行一次资源密集型任务,当一个人没有使用计算机时.此任务使用了相当大的内存块,但在任务完成后立即释放所有内存.NetBeans探查器显示内存使用情况如下所示:

我真的很想在不使用时将所有堆空间都交还给操作系统.没有理由让我把它全部用掉,而程序甚至不会在至少一个小时内做任何事情.
这可能吗?谢谢.
安装程序
.NET为段中的每一代堆(0,1,2,LOH)分配内存,以便在启动时以及在集合之后尝试满足分配请求时获得连续的内存块.
为应用程序"预热"时,为每个堆分配的内存可能会趋于平稳,除了可能用于第2代和大对象堆.在垃圾收集期间,每个堆(0,1,2)都被扫描并压缩,除了大扫描的大对象堆(LOH).
我理解集合的"扫描"部分意味着GC识别哪些对象不再有根并且可用于收集(或完成),并且'compact'意味着堆中仍然存活的地址被重新组织,因此可用的剩余堆具有更多可用的连续内存.
由于超出了堆中每个段的预算,.NET将分配另一个段以便在可能的情况下完成分配.
问题
我的问题归结为每个堆中的内存会发生什么,应用程序(已提交)不再使用,但仍由.NET保留? 什么时候发布回操作系统?.
我认为这是一个过程可能会占用大量内存的场景(虚拟大小非常大,但私有字节很小),但是当检查它的堆大多是可用空间时.作为另一个警告,堆的总大小也可能非常小,并且不考虑该过程消耗的内存.
没有阻止的终结器,并且对于一个进程看起来都很健康 - 它可能已经运行了几周才触发监视器警报(例如).
试图进一步澄清这个问题,如果您阅读Tess .NET内存管理 - 餐馆类比,如果表是堆段,餐厅是否会丢失表(例如免费堆段)?
编辑
我有一个Java控制台应用程序,它使用DOM处理大型xml文件.基本上它从数据库中获取的数据创建xml文件.现在,正如你猜测它正在使用大量内存,但令我惊讶的是,它与糟糕的代码无关,而是"Java堆空间不缩小".我尝试使用这些JVM参数从Eclipse运行我的应用程序:
-Xmx700m -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=20
Run Code Online (Sandbox Code Playgroud)
我甚至加了
-XX:-UseSerialGC
Run Code Online (Sandbox Code Playgroud)
因为我发现并行GC忽略"MinHeap"和"MaxHeap"选项.即使我的应用程序的内存使用所有这些选项图形看起来像这样:

正如您所看到的,我的应用程序在某一时刻需要大约400 MB的堆空间,堆增长到大约650 MB,但几秒钟之后(当xml生成完成时)我的应用程序下降到12MB的已用堆,但是"堆大小" "保持在650 MB左右.我的RAM需要650 MB!这是古怪的,你不觉得吗?
**有没有办法强制JVS将可用堆大小缩小到150%当前使用的堆?**就像,如果我的应用程序需要15 MB内存,堆大小约为20MB,当我的应用程序要求400 MB时在我的应用程序完成繁重的操作后,ram,堆增长到~600 MB并且DROPS回到~20 MB?