Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/381.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
最大化Java堆空间_Java_Memory Management - Fatal编程技术网

最大化Java堆空间

最大化Java堆空间,java,memory-management,Java,Memory Management,我试图在Java中使用非常大的方阵,其数量级为n=1e6或更多。矩阵不是稀疏的,所以我看不出有多少方法可以将它们表示为2D数组,这需要n^2*sizeof(int)位内存。很明显,我遇到了堆溢出错误,即使在添加编译器标志以使用尽可能大的堆时也是如此 为了这个问题,我愿意假设我有一台完美的计算机(无限内存,等等),尽管实际上我在一台64位的机器上,有16吉位的内存。我的机器似乎只与此相关,因为我受到JVM的限制,而不是我的实际硬件(JVM不能比我的物理机器拥有更多内存) 我理解(这里引用的例子)J

我试图在Java中使用非常大的方阵,其数量级为n=1e6或更多。矩阵不是稀疏的,所以我看不出有多少方法可以将它们表示为2D数组,这需要n^2*sizeof(int)位内存。很明显,我遇到了堆溢出错误,即使在添加编译器标志以使用尽可能大的堆时也是如此

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

我理解(这里引用的例子)Java数组甚至在理论上都不能大于用于索引的MAX_INT

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

我明白,如果有,他们可能不会给我更多的信息

例如

在C中,我可以声明静态常量变量,并将它们移动到代码的数据部分,这将比堆和堆栈()有更多的空间

在Java中,即使我将变量复制到“数据”部分,值也会进入主堆 这意味着我已经成功地从堆中移出了一整字节(耶!)

我的解决方案


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

不是我的问题

我不是问如何使数组超过java的最大数组大小。这是不可能的。这些是嵌套数组-单个大小为n的数组就可以了,其中n个会导致问题

我不是问这个。垃圾收集与此无关-我甚至无法让数组更不用说担心它何时被删除

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


注意:Java不是对非常大的矩阵进行操作的正确语言。我最好用算盘。但我在这里,这不在我的控制范围之内。

你最初的问题有一些缺失的方面;例如,我不能相信你必须使用如此大的矩阵,而只是在运行之间“忘记它们”。也许你会,我不知道

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

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

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


编辑:一些相关链接:

  • )
  • )
  • ,及其方法

能否在多个JVM中分发计算?例如,使用类似JPPF的东西,运行时只分配更多ram是否有效?您可以
.allocateDirect()
一些
字节缓冲
s,并使用包装类“我们从Java最快的操作之一变成了非常慢的过程”@shekhar谢谢,长期来看,这似乎是最强大的选择