Java堆空间不足错误:java.lang.OutOfMemoryError

109

我在执行多线程程序时遇到以下错误:

java.lang.OutOfMemoryError: Java heap space

上述错误发生在其中一个线程中。

  1. 据我所知,堆空间仅由实例变量占用。如果这是正确的,那么为什么在运行一段时间后会出现此错误,因为实例变量的空间在对象创建时就已分配完毕。

  2. 有没有办法增加堆空间?

  3. 我应该对我的程序进行哪些更改,以便使用较少的堆空间?


5
请访问 https://dev59.com/zXVD5IYBdhLWcg3wQZQg。该网页介绍如何处理Java堆空间错误,即OutOfMemoryError:Java Heap Space。建议通过增加Java虚拟机的堆内存来解决这个问题。 - JuanZe
12个回答

111

如果您想增加堆空间,可以在命令行中使用java -Xms<初始堆大小> -Xmx<最大堆大小>。默认情况下,这些值基于JRE版本和系统配置。您可以在Java网站上了解更多有关VM选项的信息

然而,我建议您对应用程序进行分析,以查找为什么堆大小会增长的原因。NetBeans附带了一个非常好的分析工具。我相信它在内部使用了jvisualvm。通过分析工具,您可以尝试找到创建许多对象的位置、对象何时被垃圾回收等信息。


1
我正在使用Netbeans,但我不知道如何使用分析器。我想了解更多关于分析器的信息,以便我可以使用它来查找应用程序中的内存泄漏问题。 - Amit
我添加了一个链接到NetBeans网站上的页面(http://profiler.netbeans.org/),该页面具有非常好的有关概要文件的文档,从基础知识到更高级的使用。 - Thomas Owens
默认值会随着Java版本的变化而改变,将这个信息包含在你的回答中会很好。 - Dariusz
刚解决了类似的问题,首先尝试了以下命令:java -jar division.jar -Xmx512m -Xms512m,但这给我带来了同样的错误,但当我这样做时:java -Xmx512m -Xms512m -jar division.jar,一切都正常了。所以参数顺序也很重要。 - hipokito
@hipokito 在 jar 文件后面的参数将作为 args[] 传递给 jar 文件的 main() 方法。 - Asu

30

1.- 是的,但它基本上指的是程序使用的整个内存。

2.- 是的,请查看Java VM选项。

-Xms<size>        set initial Java heap size
-Xmx<size>        set maximum Java heap size

Ie

java -Xmx2g将最大分配2GB的内存给你的应用程序。

但你应该先检查是否存在内存泄漏。

3.这取决于程序。尝试查找内存泄漏。这个问题很难回答。最近,您可以使用JConsole进行剖析,以找出内存消耗的位置。


8
您可能想查看这个网站以了解有关JVM中内存的更多信息: http://developer.streamezzo.com/content/learn/articles/optimization-heap-memory-usage 我发现使用visualgc观察内存模型的不同部分如何填充是有用的,以确定要更改的内容。
很难确定哪个部分的内存已经被填满,因此需要使用visualgc。您可能只想更改出问题的部分,而不是简单地说:

好吧!我将为JVM提供1G的RAM。

尝试更精确地描述您正在进行的操作,在长期运行中,您可能会发现程序变得更好。
要确定内存泄漏可能在哪里,您可以使用单元测试来测试,在测试之前和之后测试一下内存,如果变化太大,则可能需要检查它,但是需要在测试仍在运行时进行检查。

7

6
据我所知,堆空间仅由实例变量占用。如果这是正确的,那么为什么在运行一段时间后会出现错误,因为实例变量的空间在对象创建时就已分配好了。
这意味着您的应用程序在一段时间内不断地创建更多对象。新对象将存储在堆内存中,这就是堆内存增长的原因。
堆不仅包含实例变量。它将存储所有非基本数据类型(对象)。这些对象的生命周期可能很短(方法块)或很长(直到对象在应用程序中被引用)。
有没有办法增加堆空间?
是的。请查看 Oracle article 获取更多详细信息。
设置堆大小有两个参数: -Xms:设置初始和最小堆大小 -Xmx:设置最大堆大小
  1. 如何更改程序以减少堆空间的使用?

这取决于您的应用程序。

  1. 根据应用程序要求设置最大堆内存。

  2. 不要在应用程序中造成内存泄漏。

  3. 如果在应用程序中发现内存泄漏,请使用 MATVisual VMjconsole 等分析工具查找根本原因。一旦找到原因,修复内存泄漏。

来自 Oracle 文章 的重要提示。

原因:详细消息Java堆空间表示无法在Java堆中分配对象。此错误并不一定意味着存在内存泄漏。
可能的原因:
1.不正确的配置(未分配足够的内存);
2.应用程序无意中保留对对象的引用,从而防止这些对象被垃圾收集;
3.使用finalizer过度的应用程序。如果一个类有一个finalize方法,则该类型的对象在垃圾收集时不会回收其空间。如果finalizer线程无法跟上finalization队列,则Java堆可能会填满,并抛出此类型的OutOfMemoryError异常。
另外,可以使用更好的垃圾收集算法(CMS或G1GC)。请参阅 question 以了解G1GC。

6

要增加堆大小,您可以在启动Java时使用-Xmx参数;例如:

-Xmx256M

5
  1. 在大多数情况下,代码并没有经过优化。释放掉那些你认为以后不再需要的对象。避免在循环中每次创建对象。尝试使用缓存。我不知道你的应用程序具体如何运行。但是,在编程中,生活中的一条规则同样适用:

    预防胜于治疗。"不要创建不必要的对象"


3
  1. 本地变量位于堆栈上。对象占用堆空间。

  2. 您可以使用-Xmx选项。

  3. 基本上,每次使用new分配新对象时都会使用堆空间,并在对象不再被引用后释放。因此,请确保您不保留不再需要的对象引用。


1
不,我认为你想到的是堆栈空间。堆空间被对象占用。增加它的方法是在命令行中使用-Xmx256m,将256替换为您需要的数量。

1
我尝试了所有的解决方案,但以上的解决方案都没有起作用。
解决方案:在我的情况下,我使用的是4GB的RAM,因此RAM使用率达到了98%,所需的内存量不可用。请注意这一点。如果出现这样的问题,请升级RAM,它将正常工作。
希望这可以为某人节省时间。

1
如果使用了4GB的RAM,那么你现在有多少RAM?增加RAM之后,你是否遇到过任何内存错误的问题? - Kishan Solanki
我增加了8GB内存,现在12GB的内存可以正常工作。增加内存后,我不再遇到“java.lang.OutOfMemoryError: Java heap space”这个问题,现在它完美地运行着。 - RvSingh3213
1
但说实话,只有当你的受众超过一百万时才需要12 GB的RAM。你的用户基础如何? - Kishan Solanki
@KishanSolanki 实际上我在本地机器上遇到了这个错误。所以我浪费了太多时间寻找解决方案。因此,我发布了这个答案,以便能够帮助那些遇到本地问题的人。我认为如果你在本地遇到这个问题,我提到的解决方案会起作用。谢谢。 - RvSingh3213
我怀疑增加RAM并不是解决方案,因为您在本地运行应用程序时没有太大的负载。您的应用程序很可能存在内存泄漏问题,或者您已经配置了一些JVM参数,在8GB系统RAM下导致了问题。 - arunken

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接