java.lang.OutOfMemoryError:Java堆空间

时间:2009-10-20 17:02:55

标签: java multithreading out-of-memory heap-memory

执行多线程程序时出现以下错误

java.lang.OutOfMemoryError: Java heap space

上述错误发生在其中一个主题中。

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

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

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

12 个答案:

答案 0 :(得分:98)

如果要增加堆空间,可以在命令行上使用java -Xms<initial heap size> -Xmx<maximum heap size>。默认情况下,这些值基于JRE版本和系统配置。你可以找到more about the VM options on the Java website

但是,我建议您对应用程序进行概要分析,以找出您的堆大小被吃掉的原因。 NetBeans包含very good profiler。我相信它使用引擎盖下的jvisualvm。使用分析器,您可以尝试查找正在创建许多对象的位置,对象何时进行垃圾回收等等。

答案 1 :(得分:25)

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进行分析,以尝试找出您的内存将去哪里

答案 2 :(得分:8)

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

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

很难确定哪个部分的内存被填满,因此你可能只想更改出现问题的部分,而不仅仅是说,

  

精细!我将给JVM提供1G的RAM。

尝试更准确地了解自己在做什么,从长远来看,你可能会更好地找到它。

要确定内存泄漏的位置,您可以使用单元测试,通过测试测试之前和之后的内存,如果变化太大,那么您可能需要检查它,但是,您需要在测试仍在运行时进行检查。

答案 3 :(得分:6)

要增加堆大小,可以在启动Java时使用-Xmx参数; e.g。

-Xmx256M

答案 4 :(得分:6)

您可以通过以下程序获取堆内存大小。

public class GetHeapSize {
    public static void main(String[] args) {
        long heapsize = Runtime.getRuntime().totalMemory();
        System.out.println("heapsize is :: " + heapsize);
    }
} 

然后你可以通过使用以下方法增加堆大小: java -Xmx2g http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html

答案 5 :(得分:6)

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

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

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

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

是。有关更多详细信息,请查看此oracle article

设置堆大小有两个参数:

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

-Xmx: ,设置最大堆大小

  
      
  1. 我应该对程序进行哪些更改,以便减少堆空间?
  2.   

这取决于您的申请。

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

  2. 不要在应用程序中导致内存泄漏

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

  4. 来自oracle article

    的重要说明
      

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

    可能的原因:

    1. 配置不当(不分配足够的内存)
    2. 应用程序无意中持有对象的引用,这可以防止对象被垃圾回收
    3. 过度使用终结器的应用程序。如果类具有finalize方法,则该类型的对象在垃圾收集时不会回收它们的空间。 如果终结器线程无法跟上终结队列,那么Java堆可能会被填满,并且会抛出这种类型的OutOfMemoryError异常
    4. 另外,请使用更好的垃圾收集算法( CMS G1GC

      了解这个question以了解G1GC

答案 6 :(得分:5)

  1. 在大多数情况下,代码未经过优化。释放您认为不再需要的物体。避免每次在循环中创建对象。尝试使用缓存。我不知道你的应用程序是怎么做的。但在编程中,正常生活的一条规则也适用

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

答案 7 :(得分:3)

  1. 局部变量位于堆栈中。堆空间被物体占据。

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

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

答案 8 :(得分:1)

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

答案 9 :(得分:0)

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

答案 10 :(得分:0)

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

@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)

答案 11 :(得分:0)

我已经尝试了所有解决方案,但上述解决方案没有任何效果

解决方案:在我的情况下,我使用的是 4GB RAM,由于 RAM 使用率达到 98%,因此如果内存不可用,则所需的数量。也请务必查找此问题。如果出现此类问题,请升级 RAM,它会正常工作。

希望这能节省一些人的时间