我愿意假设我有一个完美的电脑(无限RAM等)为了这个问题,虽然在现实中,我在一个64位机器与16 gig的RAM.看来我的机器是如此相关,因为我被JVM限制,而不是我的实际硬件(因为JVM不能有比我的物理机更多的内存).
我理解(并且被引用,例如这里是Making a very large Java array),Java数组在理论上不能比用于索引的MAX_INT大.
我的问题是:是否有任何方法将额外的内存从JVM堆中哄骗
我明白,如果有的话,他们可能不会给我更多的信息.
例如
在C中,我可以声明静态常量变量,并将它们移动到代码的数据部分,该部分的空间将比堆更多,远远大于堆栈(@L_502_2@).
在Java中,似乎即使将变量复制到“数据”部分中,该值将进入主堆
static allocation in java – heap,stack and permanent generation这意味着我已经成功地从堆中移出了一整个字节(yay!)
我的解决方案
我的“解决方案”并不是真正的解决方案.我做了一个简单的数据结构,使用RandomFileAccess io过程来替换数组访问,读取和写入外部文件.它仍然是持续的时间访问,但是我们从Java的最快的操作中转移到非常慢的过程(尽管我们可以一次从文件中提取“缓存”行,这使得过程更加快速).更好的想法?
不是我的问题
我不是问如何使一个数组高于java的最大数组大小.这是不可能的.这些是嵌套数组 – 单个n个大小的数组是好的,其中n个导致问题.
我不是要求这个How to deal with “java.lang.OutOfMemoryError: Java heap space” error (64MB heap size).垃圾收集是不相关的 – 我甚至不能让数组更不用担心什么时候被删除.
我也不能使用迭代器(我认为),否则将是一种可能性;像矩阵乘法的函数需要能够直接索引
注意:Java不是在非常大的矩阵上进行操作的正确语言.我会更好的使用算盘.但我在这里,这是我无法控制的.
解决方法
无论如何:你的使用RandomAccessFile是,imho,几乎在那里;只有当我是你,我会使用FileChannel.map().在Unix系统上,它基本上是一种调用mmap(2)的方式.在下面的情况下,我假设你有一个FileChannel到你的矩阵(我认为你明白我的意思).
由于您使用矩阵,因为它看起来像矩阵中任何给定的“坐标”上的值都具有相同的长度,这意味着您可以轻松地计算文件中的偏移量以读取和/或将给定值写入矩阵.当然,你不会想映射该值,而是一个包含该值的窗口;使窗口足够大以使其有用,并且不用担心堆空间消耗:FileChannel.map()不占用空间(保存对象簿记).在64位JVM上,您不必担心;如果您使用的是32位JVM,那么您不得不考虑到地址空间耗尽.
当然,有到期的问题:你需要多长时间或者这个映射保持活跃.这完全取决于你的程序和你做什么.但是使用FileChannel并映射相关的区域是要走的路.但是,应该提醒的是,映射超过2 ^ 31 – 1个字节是不安全的;例如,确定2 ^ 30(1 GiB)个字节窗口;并提醒您可以将ByteBuffers转换为IntBuffers.
编辑:一些相关链接:
> FileChannel.open()
;
> FileChannel.map()
;
> ByteBuffer
及其asIntBuffer()
方法;
> IntBuffer
.