20

在考虑了很长时间提出这个问题的通用方法(并且没有找到)之后,我只是将它作为一个具体的例子来问:

假设我有一台 Linux 机器,它有 1 Gb 的内存,它可以分配给进程(物理和交换总计 1 Gb)。

我在机器上安装了标准的 Oracle Hotspot JVM 版本 7。如果在给定时刻,有足够多的程序正在运行,使得 1 Gb 中只有 400 Mb 是空闲的,那么我此时使用以下 JVM 标志启动一个 Java 程序:

java -Xms256m -Xmx512m -jar myJar.jar

发生了什么?:

A. JVM 是否无法立即启动,因为它将尝试分配所有 512 Mb 内存并失败(由于目前没有足够的可用内存)?

如果 JVM 启动:

如果在某个时候,正在运行的 Java 进程需要超过 400 Mb 的内存(并且除了当前 Java 进程已经使用的内存之外,仍然只有 400 Mb 的可用内存),将会发生什么:

B. Java 进程是否会因 OutOfMemroyError 而失败?

C. 它会因其他(标准)错误而失败吗?

D. 是未定义的行为吗?

4

5 回答 5

10

-Xmx 只是定义了堆的最大大小。它不能保证是否有这么多内存。它只确保堆永远不会大于给定值。也就是说,选项 B.) 将发生,将抛出 outOfMemoryError。

于 2012-11-07T13:44:38.887 回答
6

假设我有一台 Linux 机器,它有 1 Gb 的内存,它可以分配给进程(物理和交换总计 1 Gb)。

我的第一反应是,除非您在谈论电话,否则我会获得更多内存。您可以以不到 100 美元的价格购买 16 GB(b = 位,B = 字节)。

JVM 是否无法立即启动,因为它将尝试分配所有 512 Mb 内存并失败(由于目前没有足够的可用内存)?

如果您的系统没有 512 MB(加上一些开销),则可能会发生这种情况,因为它会在启动时分配用于堆的连续虚拟内存。

即使您有 550 MB 可用空间,程序也可能无法启动,因为它需要加载的不仅仅是堆。

Java 进程会因 OutOfMemoryError 而失败吗?

如果您的程序在运行时使用 512 MB,则无论您的机器有多少内存,都会发生这种情况。此错误只会在您的 JVM 启动后发生。如果它无法启动,您将不会收到此错误。

它会因其他(标准)错误而失败吗?

如果您在程序启动后用完交换空间,这是可能的。这种情况很少见,而且只发生在严重超载的机器上。我所看到的是由于低级操作系统未能分配内存而导致 JVM 崩溃。

Java 6 Update 25 VM 崩溃:内存不足

于 2012-11-07T13:43:23.193 回答
2

OutOfMemroyError将是“当 Java 虚拟机因为内存不足而无法分配对象时抛出,并且垃圾收集器无法提供更多内存。”

因此,本质上,“B. Java 进程失败并显示OutOfMemroyError

于 2012-11-07T13:42:55.120 回答
2

如果您占用的内存太多,以至于可用空间甚至无法维持空闲的 JVM,您会收到一些错误,说明程序没有足够的内存,或者 JVM 会崩溃。

如果可以运行 JVM,则可以使用 -Xmx 指定堆空间限制。这并不意味着所有堆都将在启动时由 JVM 分配 - 这只是一个内部限制。如果 JVM 想要增加堆空间,但是没有足够的内存,或者你需要比 -Xmx 指定的更多的堆,你会在当前运行的 Java 程序中得到 OutOfMemoryError。

在非常极端的情况下,您可能会在 JVM 运行时耗尽可用内存,同时 JVM 需要更多内存用于其内部操作(而不是堆空间) - 然后 JVM 会告诉您它需要更多内存,但无法得到任何,并终止,否则将彻底崩溃。

于 2012-11-07T13:50:55.057 回答
1

JVM 进程将在虚拟内存中运行,因此其他进程运行的分配问题是相关的,但不是完全决定性的。

当 JVM 无法分配更多内存时(无论出于何种原因),进程本身不会终止,而是开始在 JVMOutOfMemoryError 抛出,而不是在 JVM 外部。换句话说,JVM 继续运行,但在 JVM 中运行的程序通常会失败,因为大多数程序没有充分处理低内存条件。在这种相当常见的情况下,当程序不做任何事情来处理错误时,JVM 将终止程序并退出。最终,这是来自内存分配,但不是直接如此。一段代码有可能在内存不足的情况下自行缩减并继续运行。

其他人指出,有时 JVM 本身不能很好地处理低内存,但这是一个非常极端的情况。

于 2012-11-07T13:49:35.873 回答