java.lang.OutOfMemoryError:Java堆空间


96

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

java.lang.OutOfMemoryError: Java heap space

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

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

  2. 有什么办法可以增加堆空间?

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


Answers:


104

如果要增加堆空间,可以java -Xms<initial heap size> -Xmx<maximum heap size>在命令行上使用。默认情况下,这些值基于JRE版本和系统配置。您可以在Java网站上找到有关VM选项的更多信息

但是,我建议对应用程序进行性能分析,以查明为什么吃掉了您的堆大小。NetBeans包含一个非常好的分析器。我相信它使用jvisualvm引擎盖下。使用事件探查器,您可以尝试查找在哪里创建了许多对象,何时收集了对象的垃圾等等。


1
我正在使用Netbeans,但是我不知道如何使用事件探查器。我想了解更多有关探查器的信息,以便可以使用它来查找应用程序中的内存泄漏。
Yatendra Goel 2009年

我在NetBeans站点(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

29

1.-是的,但是它几乎是指程序使用的整个内存。

2.-是的,请参阅Java VM选项

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

java -Xmx2g 为您的应用分配2 GB的RAM作为最大内存

但是您应该先查看是否没有内存泄漏。

3.-取决于程序。尝试点内存泄漏。这个问题很难回答。最近,您可以使用JConsole进行概要分析,以尝试找出内存的存放位置


while which(true);)
Gal Bracha 2014年

8

您可能需要查看此站点,以了解有关JVM中内存的更多信息:http : //developer.streamezzo.com/content/learn/articles/optimization-heap-memory-usage

我发现使用visualgc来观察内存模型的不同部分如何填充,以确定要更改的内容很有用。

由于您可能只想更改出现问题的部分,而不是仅仅说,很难确定内存的哪一部分已被填充,因此很难确定是visualgc。

精细!我将给JVM 1G RAM。

尝试更加精确地了解您的工作,从长远来看,您可能会发现该程序更适合它。

要确定内存泄漏的位置,您可以对此进行单元测试,方法是在测试之前,之后以及之后进行测试,如果变化太大,则可能需要检查一下,但是,您需要在测试仍在运行时进行检查。


6

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

-Xmx256M


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

这意味着您将在一段时间内连续在应用程序中创建更多对象。新对象将存储在堆内存中,这就是堆内存增长的原因。

堆不仅包含实例变量。它将存储所有非原始数据类型(对象)。这些对象的寿命可能很短(方法块)或很长(直到应用程序中引用了该对象)

  1. 有什么办法可以增加堆空间?

是。请查看此oracle 文章以了解更多详细信息。

有两个参数可用于设置堆大小:

-Xms:,它设置初始和最小堆大小

-Xmx:,它设置最大堆大小

  1. 我应该对程序进行哪些更改,以便它将占用更少的堆空间?

这取决于您的应用程序。

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

  2. 不要在您的应用程序中引起内存泄漏

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

Oracle 文章中的重要说明

原因:详细消息Java堆空间指示无法在Java堆中分配对象。此错误不一定表示内存泄漏。

可能的原因:

  1. 配置正确(未分配足够的内存)
  2. 应用程序无意间保留了对对象的引用,这防止了对象被垃圾回收
  3. 过度使用终结器的应用程序。如果类具有finalize方法,则该类型的对象在垃圾回收时不会回收其空间。如果终结器线程无法跟上终结队列的速度,则Java堆可能会填满,并且会抛出此类OutOfMemoryError异常

另外,请使用更好的垃圾收集算法(CMSG1GC

看看这个问题以了解G1GC


5
  1. 在大多数情况下,代码不会得到优化。释放那些您认为不再需要的对象。避免每次在循环中创建对象。尝试使用缓存。我不知道您的应用程序运行状况如何。但是在编程中,也适用正常生活的一条规则

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


3
  1. 局部变量位于堆栈上。堆空间被对象占用。

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

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


1

不,我认为您正在考虑堆栈空间。堆空间被对象占用。增加它的方法是-Xmx256m,用您在命令行上需要的数量替换256。


1

为了避免该异常,如果您使用的是JUnit和Spring,请尝试将其添加到每个测试类中:

@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)

0

在netbeans中,转到“运行”工具栏,->“设置项目配置”->“自定义”->弹出窗口的“运行”->“ VM Option”->填写“ -Xms2048m” -Xmx2048m'。它可以解决堆大小问题。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.