最大化Java堆空间

时间:2014-11-05 06:07:44

标签: java memory-management

我正在尝试在Java中使用非常大的方形矩阵,大约为n = 1e6或更多。矩阵不是稀疏的,所以我没有看到很多方法将它们表示为2D数组,这需要n ^ 2 * sizeof(int)位的内存。显然,即使添加编译器标志以用作我的机器允许的大堆,我也会遇到堆溢出错误。

我愿意为了这个问题而假设我拥有完美的计算机(无限制的RAM等),尽管实际上我是在64位机器上使用16演出的RAM。似乎我的机器只是如此相关,因为我受JVM限制而不是我的实际硬件(因为JVM不能有更多内存而不是我的物理机器。)

我理解(并引用,例如,这里Making a very large Java array)Java数组在理论上甚至不能比用于索引的MAX_INT大。

我的问题是:有没有办法从JVM堆中哄骗额外的内存

据我所知,如果有,他们可能不会给我更多信息。

例如

在C中,我可以声明静态常量变量,并将它们移动到代码的数据部分,该部分将具有比堆更多的空间,远远超过堆栈(Where are static variables stored (in C/C++)?)。

在Java中,似乎即使我将变量复制到“数据”部分,该值也会进入主堆 static allocation in java - heap, stack and permanent generation这意味着我已经成功地从堆中移出了一整个字节(是的!)

我的解决方案

我的“解决方案”并不是真正的解决方案。我创建了一个简单的数据结构,它使用RandomFileAccess io过程来替换对外部文件的读写的数组访问。它仍然是恒定时间访问,但我们从Java最快的操作之一转到非常非常慢的过程(尽管我们可以同时从文件中提取“缓存”行,这使得该过程非常快速)。 更好的想法?

不是我的问题

我不是问如何在java的最大数组大小之上创建一个数组。这是不可能的。这些是嵌套数组 - 单个n大小的数组很好,其中n个会导致问题。

我不是问这个How to deal with "java.lang.OutOfMemoryError: Java heap space" error (64MB heap size)。垃圾收集是不相关的 - 我甚至无法让阵列更加担心何时被删除。

我也不能使用迭代器(我认为),否则这是可能的;像矩阵乘法这样的函数需要能够直接索引

注意:Java不是在非常大的矩阵上进行操作的正确语言。我最好使用算盘。但我在这里,这是我无法控制的。

1 个答案:

答案 0 :(得分:3)

您的原始问题有一些缺失的方面;例如,我无法相信你必须使用如此大的矩阵并且只是在运行之间“忘记它们”。好吧,也许你这样做,我不知道。

无论如何:你对RandomAccessFile的使用是,imho,几乎就在那里;只有我是你,我才会使用FileChannel.map()。在Unix系统上,它基本上是一种调用mmap(2)的方法。在下面的场景中,我假设你的矩阵有一个FileChannel(我认为你理解我的意思)。

由于您使用矩阵,因为看起来矩阵中任何给定“坐标”的值都具有相同的长度,这意味着您可以轻松计算文件中的偏移量以读取和/或写入给定值进入矩阵。当然,您不希望映射那个值,而是一个包含该值的窗口;使窗口大到足以使用,并且不要担心堆空间消耗: FileChannel.map()不占用堆空间(除了对象簿记)。在64位JVM上,您无需担心;如果你使用的是32位JVM,你必须考虑地址空间的耗尽。

当然,存在过期问题:您需要多长时间才能保持活动状态。这完全取决于您的程序以及您使用它做什么。但是使用FileChannel并映射相关区域是可行的方法。但是,应该提醒您,映射超过2 ^ 31 - 1个字节是不安全的;例如,解决2 ^ 30(1 GiB)字节窗口;并提醒您可以将ByteBuffer转换为IntBuffer s。


编辑:一些相关链接: