2009-04-29 16 views
1

当试图发现我的机器,我遇到了一些有趣的结果上的Java String数组的最大尺寸,这里是代码,这里的内存分配是怎么回事?

String [] max; 
    int i = 15444000; 
    while(true){ 
     try{ 
     max = new String[i]; 
     System.gc(); 
     Thread.sleep(10); 
     }catch(InterruptedException e){} 
    i += 1; 
    System.out.println(i); 
    } 

每当我运行此代码的输出使得投掷前OutOfMemoryError异常。这使我认为,我的机器上的一个Java String数组的最大尺寸为,但是如果我更换

int i = 15444000; 

int i = 15444037; // or any i between 15444037 and 15444002 

的OutOfMemoryError错误立即发生。这是为什么,我的机器上Java String数组的真正最大大小是多少?

+0

你分配给JVM多少内存? – CookieOfFortune 2009-04-29 22:05:51

+0

作为Cookie指出,GC是如此不可预测,以至于这样的测试最终并不意味着很多。 – 2009-04-29 22:16:57

回答

2

您将能够分配的阵列的最大大小取决于虚拟机的最大内存配置的大小。您可以使用-Xmxcommand line argument更改最大值。

而且http://java.sun.com/j2se/1.4.2/docs/api/java/lang/System.html#gc()状态

调用gc方法表明,朝着为了使内存回收未使用的对象的Java虚拟机的努力,他们目前占据可快速重用。当控制从方法调用返回时,Java虚拟机已尽最大努力从所有被丢弃的对象中回收空间。

所以你的差异可能是因为GC没有每次(Java虚拟机已经回收空间尽力而为)清理相同的方式。

1

我想可能会发生什么,这只是一个猜测,是JIT(即时编译器)可能会优化一些内存?第二个猜测是垃圾回收会在循环再次运行之前释放一点点内存。尝试在分配数组之前添加垃圾回收。

-1

那么,你可以争辩很多事情,但我认为正确的答案是“谁在乎?”。对于你的配置最大限度的问题的答案是“约1500万”。如果您真的想要将堆分配降至最后4个字节,请使用汇编程序编写...

P.S. 可能正在发生的事情包括早期在维护线程中使用的对象,一旦程序运行了一段时间,这些对象就变为垃圾收集。另一个海报暗示的JIT优化的另一个现象也是可能的:有一些线程开始在堆上分配小对象,然后在某些时候JIT被优化以在寄存器/堆栈中“分配”它们。但说实话,除非你发现阵列大小可以突然减半,否则我不会太担心。

0

当你以略小的尺寸运行时,GC可以从年轻/伊甸园/幸存者那一代收集记忆,并将其转移到终身代。大数组的分配是在终身代中进行的。由于GC先前已将物体移入终身区域,因此它现在的容量较小。

可能。完全取决于实施和时间安排。像这样的大分配最好通过NIO直接分配的缓冲区完成。

0

不,从您发布的代码中没有任何洞察力或真实性。如果增加可用的最大堆空间,则可以使阵列长度更高。

另一件值得了解的事情是:调用System.gc()并不意味着垃圾收集器运行。这只是一个建议。