4

在 Bash 中,我使用该java -Xmx8192m -Xms512m -jar jarfile命令启动一个初始堆空间为 512MB,最大堆空间为 8GB 的​​ Java 进程。

我喜欢堆空间如何根据需求增加,但是一旦堆空间增加,它就不会释放,尽管进程不需要内存。如何释放进程未使用的内存?

示例:进程启动,并使用 600MB 内存。堆空间从 512MB 增加到略高于 600MB。然后进程下降到 400MB RAM 使用量,但堆分配保持在 600MB。如何使分配保持在 RAM 使用率附近?

4

3 回答 3

6

你不能; 它根本不是为了那样工作而设计的。请注意,未使用的内存页面将简单地由您的硬件映射出来,因此不会消耗任何实际内存。

于 2012-07-11T18:44:25.033 回答
4

通常,您不希望 JVM 将内存返回给操作系统,然后再收回,因为这两种操作都不那么便宜。

有几个XX参数可能会或可能不会与您首选的垃圾收集器一起使用,即

  • -XX:MaxHeapFreeRatio=70 GC 后可用堆的最大百分比以避免收缩。
  • -XX:MinHeapFreeRatio=40 GC 后堆空闲的最小百分比以避免扩展。

资源

我相信您需要阻止世界收集器才能强制执行。其他 JVM 可能有自己的参数。

我通常不会回复,但负面/虚假信息的数量并不酷。

于 2012-07-11T19:26:41.937 回答
1

不,这是必需的功能。我认为,Android 中的 JVM 可能可以做到这一点,但我不确定。

但是它们中的大多数——包括所有 Java EE VM——根本对此不感兴趣。

这并不像看起来那么简单——从操作系统的角度来看,VM 是一个进程,并且在某个地方有一个映射的内存区域,它是一个堆栈或数据段。

在大多数情况下,它需要是一个连续的间隔。操作系统视图中的内存分配和释放发生在系统调用中,进程使用该系统调用向操作系统询问其新的段限制。

例如,如果您的 JVM 有 2 GB 的 RAM,它只使用 500 meg,但是这 500 meg 分散在这 2 gig 中的一些 10 字节片段中,该怎么办?此内存释放功能还需要一个碎片整理步骤,这将增加 GC 运行的资源成本。

随着 Java 的运行,垃圾收集器构造和销毁 Java 对象,空闲和分配的内存区域分散在堆栈/数据段中。

当我们看不到java,而是native OS进程时,情况是一样的:如果你malloc() 10个1meg块,然后释放前9个,就没有办法把它还给OS,尽管较新的库和 os apis 对此有广泛的发展。当然,如果您稍后再次分配内存,则此分配将从刚刚释放的区域中完成。

我的观点是,即使这有点昂贵和复杂(并且是一项相当大的编程工作),它也物有所值,而且我认为这不是我们集体编程文化中最好的形象,它不是几十年来所做的一切,包括java vms。

于 2013-01-04T20:06:06.173 回答