Java垃圾收集是否开始起作用以防止内存交换?

时间:2010-08-23 11:27:27

标签: java garbage-collection

举一个例子,我可以说我将JVM的最大堆设置为4GB。但是,一旦我的应用程序达到大约3GB,操作系统就开始将一些内存交换到磁盘。此时有几个对象已经超出范围,而JVM可能首先垃圾收集旧对象,而不是请求更多内存。在性能方面,进行垃圾收集运行比进行内存交换更好。 JVM垃圾收集是否是关于这样的情况的智能,还是完全没有意识到它?我们可以以某种方式调整JVM来解决这种情况吗?

我知道垃圾收集有可能在我们达到3GB之前运行,因此我们实际上不需要交换内存,但这并没有真正回答我的问题。

修改 假设我的机器有超过4GB的内存,但有时还有其他应用程序占用了一些内存,使我的内存少于4GB。我宁愿不必减少最大堆,因为大多数时候我会有4GB但是我想知道GC在其他情况下是否足够聪明。

3 个答案:

答案 0 :(得分:8)

JVM幸福地没有意识到底层操作系统内存管理。我记得不久前参加了关于GC优化的JavaOne会议,发言者强调你应该始终确保有足够的空闲内存(RAM,而不是交换)来运行JVM,以避免不惜一切代价进行分页,所以永远不要为JVM分配的内存比系统中给定时间可用的内存多。更重要的是,由于某些GC采集算法的工作方式,如果他们收集的内存块被分页,则可能会产生巨大的性能损失。

因此,永远不要给JVM提供比系统中物理可用内存更多的内存,或者如果您希望内存消耗随着时间的推移而增加,因为某些外部进程会分配一个堆空间,以确保它永远不会被分页。如果你不能满足这些条件,那么你需要更多的RAM:)

更新:在SO中进行了一些搜索,我找到了this。在这里,kdgregory认为分页不应该是一个问题,因为GC的工作方式,但他正在考虑由于正常情况下的分页,即内存没有被触摸一段时间,这不是你的情况,因为你将用完内存,你一定会开始分页。另外,如果你正在运行一些Linux风格,请检查John Ferminella的答案和他的great blog post,解释如何理解和调整Linux中的交换。

答案 1 :(得分:2)

GC不知道这种情况。您不应指定比计算机上的可用内存量更大的堆。解决方案是减少堆大小,并确保没有其他程序占用所有内存。

实际上不要认为即使在C中也有一种简单的方法可以检查流程是否交换(也许有,如果是,请添加评论)。

答案 2 :(得分:1)

  

[...]运行时数据区域的内存布局,使用的垃圾收集算法以及Java虚拟机指令的任何内部优化(例如,将它们转换为机器代码)由酌情决定实施者。 (Java Virtual Machine Specification, Chapter 3)

没有像 Java垃圾收集这样的东西。 java虚拟机规范告诉每个jvm实现需要提供gc,但它是如何完成的留给实现者。

从技术上讲,这至少是一个挑战。因为我们不希望触发gc,因为某些页面已经交换到虚拟内存但我们希望在内存管理即将交换 jvm时触发gc页面到虚拟内存。我怀疑这些信息/通知在计算机系统中是否可用。

“操作系统到JVM:嘿,现在在将一些堆交换到虚拟内存之前更好地清理” - “JVM到操作系统:好的,请不要交换,现在开始清理,告诉你当完成“ - 1457ms之后 - ”JVM到操作系统:感谢您的耐心,尽可能地清理,您可以继续交换