2

我有一个问题。假设我有两个参数传递给 JVM: -Xms256mb -Xmx1024mb 在程序开始时分配了 256MB。接下来,创建一些对象,JVM 进程尝试分配更多内存。假设 JVM 需要分配 800MB。Xmx 属性允许这样做,但系统上当前可用的内存(比如说 Linux/Windows)是 600MB。是否有可能抛出 OutOfMemoryError ?或者也许交换机制会起作用?

我的第二个问题与 GC 算法的质量有关。假设我有 jdk1.5u7 和 jdk1.5u22。是否有可能在后一个 JVM 中内存泄漏消失并且 OutOfMemoryError 不会发生?最新版本的GC质量能更好吗?

4

4 回答 4

2

GC 的质量(除非有错误的 GC)不会影响内存泄漏,因为内存泄漏是应用程序的产物—— GC 无法收集不是实际垃圾的东西。

如果 JVM 需要更多内存,它将从系统中获取。如果系统可以交换,它将交换(与任何其他进程一样)。如果系统无法交换,您的 JVM 将失败并出现系统错误,而不是 OOM 异常,因为系统无法满足请求,这一点实际上是致命的。

作为一项规则,您永远不想让活动的 JVM 部分换出。当系统在虚拟内存系统中循环页面时,GC 事件会让你崩溃。将空闲的后台 JVM 作为一个整体换出是一回事,但是如果您的机器是 1G 的 RAM,而您的主进程需要 1.5GB,那么您就有一个大问题。

JVM 喜欢呼吸的空间。我已经看到 JVM 在没有足够内存时陷入 GC 死亡螺旋,即使它们没有内存泄漏。他们根本没有足够的工作集。添加另一块堆将 JVM 从糟糕的锯齿状 GC 图转变为快乐的锯齿状 GC 图。

给JVM它需要的内存,你会更快乐。

于 2012-08-10T17:29:21.983 回答
2

“内存”和“RAM”不是一回事。内存包括虚拟内存(交换),因此您可以在出现 OutOfMemoryError 之前分配总共可用的 RAM + 可用交换。

于 2012-08-10T17:29:47.790 回答
0

分配取决于使用的操作系统。如果您分配了太多内存,也许您最终可能会将部分加载到交换中,这很慢。如果你的程序运行得更慢,取决于 VM 如何处理内存。

我不会指定一个不太大的堆来确保它不会占用所有内存,从而防止 VM 变慢。

于 2012-08-10T17:27:17.973 回答
-1

关于您的第一个问题:
实际上,如果机器无法将1024您要求的 MB 分配为最大堆大小,它甚至不会启动 JVM。
我知道这一点是因为我注意到它经常试图打开具有大堆大小的 Eclipse,并且操作系统无法分配 JVM 无法加载的更大堆空间。您也可以自己尝试确认。所以其余的细节与你无关。当然,如果您的程序使用太多交换(与所有语言相同),那么性能将非常糟糕。

关于你的第二个问题:

内存泄漏消失了

不可能,因为它们是必须修复的错误

并且 OutOfMemoryError 不会发生?最新版本的GC质量能更好吗?

这可能会发生,例如,如果在 GC 中使用了一些不同的算法,并且它设法在您看到异常之前启动。但是,如果您有内存泄漏,那么它可能会掩盖它,或者您会看到它断断续续。
各种 JVM 也有不同的 GC,您可以配置

更新:
我不得不承认(在看到@Orochi 注释之后)我注意到 Windows 上最大堆的行为。我不能肯定地说这也适用于 linux。不过你可以自己试试。

更新 2:作为对来自IBM 的@DennisCheung 评论的回答(我的重点):

该表显示了可能的最大 Java 堆和最大 Java 堆大小设置的建议限制......重要的是拥有比机器上所有进程组合所需的更多物理内存,以防止分页或交换。分页会降低系统的性能并影响 Java 内存管理系统的性能。

于 2012-08-10T17:16:47.857 回答