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

Java垃圾收集是否开始工作以防止内存交换?,java,garbage-collection,Java,Garbage Collection,例如,假设我将JVM的最大堆设置为4GB。然而,一旦我的应用程序达到3GB左右,操作系统就会开始将一些内存交换到磁盘。此时有几个对象已经超出范围,JVM可以首先对旧对象进行垃圾收集,而不是请求更多内存。就性能而言,运行垃圾收集比执行内存交换更好。 JVM垃圾收集在这种情况下是明智的还是完全没有意识到这一点?我们能否以某种方式调整JVM以解决这种情况 我知道垃圾收集有可能在我们达到3GB之前运行,因此我们实际上不需要交换内存,但这并不能真正回答我的问题 编辑: 让我们假设我的机器有超过4GB的内存

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

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

编辑:
让我们假设我的机器有超过4GB的内存,但有时其他应用程序占用了部分内存,而我的内存不足4GB。考虑到大多数情况下我会使用4GB,我宁愿不减少最大堆化,但我想知道GC在其他情况下是否足够智能。

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

实际上,即使在C语言中,也不认为有一种简单的方法可以检查进程是否正在交换(可能有,如果有,请添加注释)

[…]运行时数据区域的内存布局、使用的垃圾收集算法以及Java虚拟机指令的任何内部优化(例如,将其转换为机器代码)都由实现者自行决定

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

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


“操作系统到JVM:嘿,在我将堆的一部分交换到虚拟内存之前,最好现在清理”-“JVM到操作系统:好的,请不要交换,现在开始清理,完成后告诉你”-1457毫秒后-“JVM到操作系统:感谢您的耐心,尽可能地清理干净,您现在可以继续交换了)

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

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


更新:做了一点搜索,所以我发现。在这里,kdgregory认为,由于GC的工作方式,分页不应该是一个问题,但他正在考虑正常情况下的分页,即内存暂时不被触摸,这不是您的情况,因为您将耗尽内存,您肯定会开始分页。另外,如果您正在运行一些Linux风格的程序,请检查John Ferminella的回答以及他解释如何理解和调整Linux中的交换。

在C语言中,您自己管理内存分配,因此您的内存中不应该有不再需要的数据。假设您在回收不再使用的内存方面做得很好,如果操作系统正在交换,则意味着不再有未使用的内存。对于java来说,这不一定是真的。感谢您的回复。你完全正确,我本应该更干净的。我想到了Sun的JVM,但同样有趣的是,如果有一个实现可以做到这一点。