我正在尝试创建一个非常大的链表,如下所示,但它失败了(在maven中作为单元测试运行。已经通过运行“set MAVEN_OPTS = -Xmx4096m”设置了堆大小(我在Windows中运行)
将大约6M(6000000)长项插入列表后代码失败。为什么?考虑到Long类型是8个字节,6M Long类型变量只是48M字节。即使Java对象有一些额外的隐藏字段,它也不应该这么早失败。
int N = 100000000;
try {
LinkedList<Long> buffer = new LinkedList<Long> ();
for(int i=0;i<N;++i) {
buffer.add((long)i);
if (i % 1000000 == 0) {
System.out.println("added " + i);
}
}
catch(Exception e)
{...}
答案 0 :(得分:4)
列表中的每个条目都是一个单独的对象,引用了前一个节点和下一个节点,以及当前值。
如果我们假设每个引用有8个字节,并且对象开销为16个字节,那意味着每个条目都有:
所以6000000条目之后大概是384M ......你应该还是可以的。 (根据您的JVM,我希望参考大小和每个对象的开销也会降低。)
我想知道您的MAVEN_OPTS是设置在错误的位置,还是由于某种原因未用于JVM参数。我刚尝试在我的Windows机器上运行它(不是作为单元测试 - 就像main
方法一样)并且使用JVM默认分配,它在我也有600万个条目后失败了。使用-Xmx1024M
它可以获得2500万个条目,这意味着开销比我上面估计的要小。 (虽然我在32位虚拟机上。)
这肯定表明你的MAVEN_OPTS没有做你想要的......
答案 1 :(得分:2)
LinkedList是存储一系列long的最低内存效率的方法。你有一个Long对象,它比一个普通长度大3倍,你有一个双链接的链接列表条目使它比普通长度大5倍。
我提到你使用long[]
或者像TLongArrayList这样的包装器,它对于大型集合每长度使用近8个字节。 (它也会更快)
答案 2 :(得分:1)
不要忘记
占用的内存LinkedList$Entry