当JVM在运行时耗尽内存以进行分配时会发生什么?

在思考了一个通用的方法来提出这个问题(并且没有找到一个)后,我只想问它作为一个具体的例子:

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

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

java -Xms256m -Xmx512m -jar myJar.jar 

发生了什么? :

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

如果JVM启动:

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

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

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

D.是不确定的行为?

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

假设我有一台具有1 Gb内存的Linux机器,它可以分配给进程(物理和交换总数为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崩溃:内存不足

当Java虚拟机无法分配对象时, OutOfMemroyError“抛出,因为它没有内存,并且垃圾收集器不能再提供更多内存。”

因此,实质上, “B. Java进程因OutOfMemroyError失败”

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

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

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

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

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

其他人已经指出,有时JVM本身并不能很好地处理低内存,但这是一个相当极端的条件。