什么是内存分配在这里?

时间:2009-04-29 21:59:55

标签: java memory

尝试在我的机器上发现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之前使其 15444038 。这让我认为我机器上的Java String数组的最大大小是 15444038 ,但是如果我替换

int i = 15444000;

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

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

5 个答案:

答案 0 :(得分:2)

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

另外http://java.sun.com/j2se/1.4.2/docs/api/java/lang/System.html#gc()个州

  

调用gc方法表明Java虚拟机花费了大量精力来回收未使用的对象,以使其当前占用的内存可用于快速重用。当控制从方法调用返回时,Java虚拟机已尽最大努力从所有丢弃的对象中回收空间。

因此,您的差异可能是因为GC每次都没有以相同的方式清理( Java虚拟机已尽最大努力回收空间)。

答案 1 :(得分:1)

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

答案 2 :(得分:0)

当您使用稍小的尺寸运行时,GC可以从年轻/伊甸园/幸存者一代收集内存并将其移动到终身代。大数组的分配是在终生代中进行的。由于GC先前已将对象移动到终身区域,因此现在容量较小。

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

答案 3 :(得分:0)

不,您发布的代码没有任何见解或真相。如果增加可用的最大堆空间,则可以使该数组长度更高。

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

答案 4 :(得分:-1)

嗯,你可以争论很多东西,但我认为正确的答案是“谁在乎?”。您的配置最大化问题的答案是“大约1500万”。如果你真的想担心堆分配到最后4个字节,请在汇编程序中编程......

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