103

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

java.lang.OutOfMemoryError: Java heap space

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

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

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

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

4

12 回答 12

108

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

但是,我建议您分析您的应用程序以找出您的堆大小被占用的原因。NetBeans 包含一个非常好的分析器。我相信它使用jvisualvm引擎盖下。使用分析器,您可以尝试查找在何处创建了许多对象、对象何时被垃圾收集等等。

于 2009-10-20T17:08:22.643 回答
30

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

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

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

IE

java -Xmx2g为您的应用程序分配最多 2 GB 的内存

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

3.- 这取决于程序。尝试发现内存泄漏。这个问题将很难回答。最近你可以使用 JConsole 来分析你的内存去向

于 2009-10-20T17:09:14.147 回答
8

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

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

很难确定内存的哪一部分已被填满,因此使用了 visualgc,因为您可能只想更改有问题的部分,而不仅仅是说,

美好的!我会给JVM 1G RAM。

尝试更准确地了解您正在做什么,从长远来看,您可能会发现该程序更适合它。

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

于 2009-10-20T17:09:33.687 回答
8

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

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

于 2013-12-18T11:04:35.010 回答
6

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

-Xmx256M
于 2009-10-20T17:07:18.177 回答
6
  1. 据我所知,堆空间仅由实例变量占用。如果这是正确的,那么为什么在运行良好一段时间后会发生此错误,因为在创建对象时分配了实例变量的空间。

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

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

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

是的。有关更多详细信息,请查看此 Oracle文章

设置堆大小有两个参数:

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

-Xmx:,设置最大堆大小

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

这取决于您的应用程序。

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

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

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

oracle文章的重要说明

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

可能的原因:

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

另一方面,使用更好的垃圾收集算法(CMSG1GC

看看这个问题以了解 G1GC

于 2016-02-15T12:02:24.900 回答
5
  1. 在大多数情况下,代码没有优化。释放那些你认为不再需要的对象。避免每次都在循环中创建对象。尝试使用缓存。我不知道你的应用程序是如何做的。但是在编程中,一条正常生活的规则也适用

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

于 2009-10-22T17:28:39.243 回答
3
  1. 局部变量位于堆栈上。堆空间被对象占用。

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

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

于 2009-10-20T17:09:29.420 回答
1

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

于 2009-10-20T17:07:50.180 回答
1

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

@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
于 2019-01-15T09:00:17.700 回答
1

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

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

希望这会节省一些时间

于 2021-05-20T12:00:31.707 回答
0

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

于 2017-06-12T22:49:25.313 回答