运行Java代码时内存不足
我有一个保存为文本文件的数据集,基本上包含一行一行存储的向量。我的向量是10维的,我有250个这样的向量。每个向量条目都是双精度的。下面是一个例子: 向量1->0.0.0.0 0.439367 0.0…..10k此类条目 向量2->0.0.0.0 0.439367 0.0 0.0.0.0 0.0…..10k此类条目 向量250->0.0 1.203973 0.0 0.0 0.0…..10k此类条目 现在,如果我进行计算,这应该占用10k X 16字节X 250空间(假设每个向量条目都是一个双字节,占用16字节的空间),即~40MB的空间。但是我看到文件大小仅显示为9.8MB。我哪里出了问题吗 问题是我在Java代码中使用了这些数据。我的算法的空间复杂度是O(向量中的条目数X条目数)。即使我通过分配4GB内存来运行代码,堆空间仍然不足。我错过了什么 谢谢。运行Java代码时内存不足,java,heap,Java,Heap,我有一个保存为文本文件的数据集,基本上包含一行一行存储的向量。我的向量是10维的,我有250个这样的向量。每个向量条目都是双精度的。下面是一个例子: 向量1->0.0.0.0 0.439367 0.0…..10k此类条目 向量2->0.0.0.0 0.439367 0.0 0.0.0.0 0.0…..10k此类条目 向量250->0.0 1.203973 0.0 0.0 0.0…..10k此类条目 现在,如果我进行计算,这应该占用10k X 16字节X 250空间(假设每个向量条目都是一个双
Andy在没有看到代码的情况下,我不能肯定地说,但是当您a)从文件中读取数据或b)在算法中的某个地方时,听起来您的分配过度了。我建议您使用visualVM之类的工具来检查对象分配—它将能够告诉您如何分配以及您犯了哪些错误 现在如果我算一下,这应该需要 最多10k X 16字节X 250空间(假设 每个向量项都是一个双值项 最多16字节的空间),即约40MB的 空间但是我看到这个文件 尺寸仅显示为9.8MB。我是吗 哪里出错了 错误的地方在于假设每个
double
保存为文本时占用16字节的空间。您似乎有很多0值,它们以字符串形式(包括分隔符)仅占用4个字节
即使我通过分配
就像4GB内存一样,我的内存仍然不足
堆空间。我错过了什么
这取决于你的代码。一个原因可能是您正在将数据存储在
ArrayList
或(更糟的是)TreeSet
-双包装器对象将导致200%的内存开销,并且Set/Map结构更糟糕。如果不看到代码和VM参数,很难说。但请注意,算法中的变量也会消耗内存。文件大小和内存使用情况取决于如何构造内存中的对象,例如,没有双精度的简单对象本身会占用空间
获取一个适当的工具来测试内存使用情况。看看这本书
另外,您可能想签出。如果我们看不到代码(这很公平),我能说的就是在启动应用程序时使用-XX:+HeapDumpOnOutOfMemoryError
命令行选项,然后在很多人猜测大小后,使用jhat
分析结果堆转储,我已经做了3个简单的测试,并使用Eclipse内存分析器来确定大小。(Win7,1.6.0_21 Java热点(TM)64位服务器虚拟机)
double[][]
=大小:19,2MB类:328个对象:2,7k
Double[][]结构
=大小:76.5MB类:332个对象:2.5m
ArrayList
=大小:79,6MB类:330个对象:2,5m
256MB(java-Xmx256m巨量
)足以运行测试
所以我想问题不在于尺寸,可能是两件事:
- 算法中有一个错误
- jvm不使用4GB运行
如果有人对代码感兴趣:
import java.util.ArrayList;
import java.util.List;
public class Huge {
private static final int NUMBER_OF_VECTORS = 250;
private static final int VECTOR_SIZE = 10000;
//Size: 19,2 MB Classes: 328 Objects: 2,7k
public static void doulbeArray() {
double[][] structure = new double[NUMBER_OF_VECTORS][];
for(int i = 0; i < NUMBER_OF_VECTORS; i++) {
structure[i] = new double[VECTOR_SIZE];
}
}
//Size: 76,5 MB Classes: 332 Objects: 2,5m
public static void doubleWrapperArray() {
Double[][] structure = new Double[NUMBER_OF_VECTORS][];
for(int i = 0; i < NUMBER_OF_VECTORS; i++) {
structure[i] = new Double[VECTOR_SIZE];
for (int k = 0; k < VECTOR_SIZE; k++) {
structure[i][k] = Double.valueOf(Math.random());
}
}
}
//Size: 79,6 MB Classes: 330 Objects: 2,5m
public static void list() {
List<List<Double>> structure = new ArrayList<List<Double>>();
for(int i = 0; i < NUMBER_OF_VECTORS; i++) {
List<Double> vector = new ArrayList<Double>();
for (int k = 0; k < VECTOR_SIZE; k++) {
vector.add(Double.valueOf(Math.random()));
}
structure.add(vector);
}
}
}
import java.util.ArrayList;
导入java.util.List;
公共类巨大{
_向量的私有静态最终整数=250;
私有静态最终整数向量_SIZE=10000;
//大小:19,2MB类:328个对象:2,7k
公共静态无效双耳环(){
double[][]结构=新的double[向量的数量][];
for(int i=0;i<向量的个数;i++){
结构[i]=新的双[VECTOR_SIZE];
}
}
//大小:76.5 MB类别:332个对象:2.5米
公共静态void doubleWrapperArray(){
Double[][]结构=新的Double[向量的数量][];
for(int i=0;i<向量的个数;i++){
结构[i]=新的双[VECTOR_SIZE];
对于(int k=0;k
看不到代码是不可能的。顺便说一句,double
只有8字节长,但这在很大程度上是不相关的,因为我们看不到代码。我们缺少源代码。仅从您的描述来看,似乎128MB就足够了。你在加载数据或后期处理方面有问题吗?@biziclop:可能安迪在向量中使用了java.lang.Double
。那么对于32位模式的热点Java虚拟机来说,16个字节是正确的。我猜是16个字节,因为64位?或者他错了。我相信你的意思是“-XX:+heapdumponootfmemoryerror”?@eggsyntax是的,当然,我是个白痴。我想避免打字错误,所以我从官方文档中复制了它。你有没有试过用大量的jhat
?我这样做了,我必须将jhat
的堆大小设置为原始文件大小的至少五倍。在等待jhat
一个多小时后,为了解析大约3GB的堆,我决定jhat
不再是我首选的工具。现在我将Eclipse与