【问题标题】:Heap space out of memory堆空间内存不足
【发布时间】:2011-10-08 13:43:31
【问题描述】:

我的应用程序目前消耗了大量内存,因为它正在运行物理模拟。问题是,在第 51 次模拟时,Java 通常会因为堆空间内存不足而抛出错误(我的程序最终会运行数千次模拟)。

有没有我不仅可以增加堆空间,还可以修改我的程序,以便在每次运行后清除堆空间,以便我可以运行任意数量的模拟?

编辑:谢谢大家。事实证明,模拟器软件在每次运行后都没有清除信息,而我将这些运行都存储在 ArrayList 中。

【问题讨论】:

  • 听起来像是内存泄漏
  • 如果随着您运行越来越多的模拟,您的内存占用量越来越大,那么您就有了内存泄漏。你需要弄清楚为什么你的记忆在模拟结束时没有被回收。
  • 是的,可能是内存泄漏,我不记得名字了,但它是一个 IBM 应用程序,它可以让您直观地看到每个线程和堆栈。几年前,这个工具帮助我们找到了 hibernate 的内存泄漏问题。将尝试用该名称更新您。
  • @randomafk:模拟是否相互依赖?你的程序是正确的多线程的吗?如果是 "no""no",那么“修复”问题的一种非常简单的方法是从 shell 脚本执行模拟。即使您的 Java 应用程序是单线程的,您也只能收集结果,甚至可以在 x 个内核上运行模拟。除此之外,显而易见的解决方案不是“清除”堆空间,而是 a) 停止泄漏内存并且 b) 使用更少内存消耗的方法(例如通过使用比默认 Java 更好的库,例如 Trove)。

标签: java memory physics heap-memory


【解决方案1】:

由于堆是在 Java 虚拟机启动时分配的,因此无法以编程方式动态增加堆。

但是,你可以使用这个命令

java -Xmx1024M YourClass

将内存设置为 1024

或者,您可以设置一个最小最大值

java -Xms256m -Xmx1024m YourClassNameHere

【讨论】:

  • 这不是“min”而是“starting”内存选项(因此“ms”标志中的“s”)跨度>
【解决方案2】:

如果您正在使用大量内存并面临内存泄漏,那么您可能需要检查您是否使用了大量 ArrayLists 或 HashMaps,每个都有很多元素。

ArrayList 实现为dynamic array。 Sun/Oracle 的源代码显示,当将新元素插入完整的ArrayList 时,会创建一个大小为原始数组 1.5 倍的新数组,并将元素复制过来。这意味着您可能会浪费您使用的每个ArrayList 中多达50% 的空间,除非您调用它的trimToSize 方法。或者更好的是,如果您事先知道要插入的元素的数量,则使用初始容量作为参数调用构造函数。

我没有仔细检查HashMap 的源代码,但乍一看似乎每个HashMap 中的数组长度必须是2 的幂,使其成为动态数组的另一种实现。请注意,HashSet 本质上是HashMap 的包装。

【讨论】:

    【解决方案3】:

    您可以使用多种工具来帮助诊断此问题。 JDK 包含JVisualVM,它允许您附加到正在运行的进程并显示哪些对象可能会失控。 Netbeans 有一个运行良好的包装器。 Eclipse 有 Eclipse 内存分析器,这是我最常使用的一个,它似乎可以更好地处理大型转储文件。还有一个命令行选项-XX:+HeapDumpOnOutOfMemoryError,它将为您提供一个文件,该文件基本上是您的程序崩溃时进程内存的快照。您可以使用上面提到的任何工具来查看它,它在诊断这类问题时真的很有帮助。

    根据程序的工作强度,可能是 JVM 不知道何时进行垃圾收集的简单情况,您也可以查看并行垃圾收集选项。

    【讨论】:

    【解决方案4】:

    我也遇到了同样的问题。我按照以下步骤进行构建解决了。

    -->右键项目选择RunAs ->运行配置

    选择您的项目作为 BaseDirectory。代替目标给 eclipse:eclipse install

    -->在第二个选项卡中将 -Xmx1024m 作为 VM 参数。

    【讨论】:

      【解决方案5】:

      我想补充一点,这个问题类似于常见的Java内存泄漏。

      当 JVM 垃圾收集器随着时间的推移无法清除 Java / Java EE 应用程序的“浪费”内存时,OutOfMemoryError: Java heap space 将是结果。

      首先进行正确的诊断很重要:

      • 启用verbose:gc。这将使您能够了解内存随时间的增长模式。
      • 生成并分析JVM Heap Dump。这将使您能够了解您的应用程序内存占用并查明内存泄漏的来源。
      • 您还可以使用 Java 分析器和运行时内存泄漏分析器(例如 Plumbr)来帮助您完成此任务。

      【讨论】:

        【解决方案6】:

        尝试添加 -Xmx 以获得更多内存 (java -Xmx1024M YourClass),并且不要忘记停止引用您不再需要的变量(内存泄漏)。

        【讨论】:

          【解决方案7】:

          您是否保留了对不再需要的变量的引用(例如来自之前模拟的数据)?如果是这样,您有内存泄漏。您只需要找到发生这种情况的位置,并确保在不再需要时删除对变量的引用(如果它们超出范围,这将自动发生)。

          如果您确实需要内存中以前模拟的所有数据,则需要增加堆大小或更改算法。

          【讨论】:

            【解决方案8】:

            当不再引用所有对象时,Java 应该为您清除堆空间。虽然它通常不会将其释放回操作系统,但它会保留该内存以供其内部重用。也许检查一下你是否有一些没有被清除的数组。

            【讨论】:

              【解决方案9】:

              没有。垃圾收集器会在需要时清除堆。您可以要求它运行(使用System.gc()),但不能保证运行。

              首先尝试通过设置-Xmx256m来增加内存

              【讨论】:

                猜你喜欢
                • 2012-04-17
                • 2021-11-20
                • 1970-01-01
                • 2012-02-22
                • 2020-01-23
                • 2014-01-04
                • 1970-01-01
                • 2023-03-17
                相关资源
                最近更新 更多