我的应用程序目前消耗相当多的内存,因为它正在运行物理模拟。问题在于,在第 51 次模拟时,Java 通常会因为堆空间内存不足而抛出错误(我的程序最终运行了数千次模拟)。
无论如何,我不能只增加堆空间而是修改我的程序,以便在每次运行后清除堆空间,以便我可以运行任意数量的模拟?
编辑:谢谢各位。结果模拟器软件在每次运行后都没有清除信息,我将这些运行全部存储在ArrayList
.
我的应用程序目前消耗相当多的内存,因为它正在运行物理模拟。问题在于,在第 51 次模拟时,Java 通常会因为堆空间内存不足而抛出错误(我的程序最终运行了数千次模拟)。
无论如何,我不能只增加堆空间而是修改我的程序,以便在每次运行后清除堆空间,以便我可以运行任意数量的模拟?
编辑:谢谢各位。结果模拟器软件在每次运行后都没有清除信息,我将这些运行全部存储在ArrayList
.
如果您使用了大量内存并面临内存泄漏,那么您可能需要检查是否使用了大量ArrayList
s 或HashMap
每个 s 具有许多元素。
AnArrayList
实现为动态数组。Sun/Oracle 的源代码显示,当一个新元素插入到 full 中时ArrayList
,会创建一个大小为原始数组 1.5 倍的新数组,并将元素复制过来。这意味着ArrayList
,除非您调用其trimToSize
方法,否则您可能会在每次使用时浪费多达 50% 的空间。或者更好的是,如果您事先知道要插入的元素数量,则使用初始容量作为参数调用构造函数。
我没有HashMap
非常仔细地检查源代码,但乍一看似乎每个数组的长度HashMap
必须是 2 的幂,这使它成为动态数组的另一种实现。请注意,HashSet
它本质上是围绕HashMap
.
您可以使用多种工具来帮助诊断此问题。JDK 包括JVisualVM,它允许您附加到正在运行的进程并显示哪些对象可能会失去控制。Netbeans 有一个包装器,效果很好。Eclipse 有 Eclipse 内存分析器,这是我最常使用的分析器,它似乎可以更好地处理大型转储文件。还有一个命令行选项,-XX:+HeapDumpOnOutOfMemoryError,它将为您提供一个文件,该文件基本上是程序崩溃时进程内存的快照。您可以使用上述任何工具来查看它,它在诊断此类问题时确实有很大帮助。
根据程序运行的难度,可能是 JVM 不知道垃圾收集的好时机的一个简单情况,您也可以查看并行垃圾收集选项。
我也遇到了同样的问题。我通过按照以下步骤进行构建来解决。
-->在项目上右击选择RunAs->Run配置
选择您的项目作为 BaseDirectory。代替目标给 eclipse:eclipse install
-->在第二个选项卡中,将 -Xmx1024m 作为 VM 参数。
我想补充一点,这个问题类似于常见的 Java 内存泄漏。
当 JVM 垃圾收集器无法随着时间的推移清除 Java/Java EE 应用程序的“浪费”内存时,结果将是OutOfMemoryError: Java heap space。
首先进行正确的诊断很重要:
尝试添加 -Xmx 以获得更多内存 ( java -Xmx1024M YourClass
),并且不要忘记停止引用您不再需要的变量(内存泄漏)。
您是否保留对不再需要的变量的引用(例如来自先前模拟的数据)?如果是这样,你有内存泄漏。您只需要找到发生这种情况的地方,并确保在不再需要变量时删除对变量的引用(如果它们超出范围,这将自动发生)。
如果您确实需要内存中先前模拟的所有数据,则需要增加堆大小或更改算法。
当不再引用所有对象时,Java 应该为您清除堆空间。虽然它通常不会将其释放回操作系统,但它会保留该内存以供其内部重用。也许检查一下您是否有一些未被清除的数组或其他东西。
不会。垃圾收集器会在需要时清除堆。您可以要求它运行(使用System.gc()
),但不能保证运行。
首先尝试通过设置增加内存 -Xmx256m
由于堆是在 Java 虚拟机启动时分配的,因此无法以编程方式动态增加堆。
但是,您可以使用此命令
将内存设置为 1024
或者,您可以设置最小最大值