tags:

views:

180

answers:

5

While trying to discover the max size of a Java String array on my machine I ran into some interesting results, here is the code,

   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);
   }

Whenever I run this code the output makes it 15444038 before throwing OutOfMemoryError. This leads me to think that the max size of a Java String array on my machine is 15444038, however if i replace

int i = 15444000;

with

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

The OutOfMemoryError occurs instantly. Why is this, and what is the true max size of a Java String array on my machine?

+2  A: 

The maximum size of the array that you will be able to allocate depends on how large the maximum memory for the VM is configured. You can change the maximum with the -Xmx command line argument.

Also http://java.sun.com/j2se/1.4.2/docs/api/java/lang/System.html#gc() states

Calling the gc method suggests that the Java Virtual Machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse. When control returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all discarded objects.

So your discrepancy may be because the GC did not clean up the same way every time (the Java Virtual Machine has made a best effort to reclaim space).

lothar
+1  A: 

I think what might be happening, and this is just a guess here, is the JIT (Just in time compiler) might be optimizing some of the memory? A second guess would be the garbage collect frees up just a little bit of memory before the loop is run again. Try adding a garbage collect before you allocate the array.

CookieOfFortune
A: 

Well, you could argue lots of things, but I think the correct answer is "who cares?". The answer to your question of what the maximum is with your configuration is "about 15 million". If you really want to worry about heap allocation down to the last 4 bytes, program in assembler...

P.S. Things that could be happening include objects used early on in a maintenance thread which becomes garbage-collectable once the program's been running a bit. Another phenomenon of JIT-optimisation that another poster hinted at is also potentially possible: there are some threads that start off allocating small objects on the heap, then at some point are JIT-optimnised to "allocate" them in registers/the stack. But honestly, unless you're finding that the array size you can allocate suddenly halves, I really wouldn't worry about it too much.

Neil Coffey
I'm not worried about it, in fact I most likely will never have to create an array of this size. I'm just having fun with Java.
ForYourOwnGood
Well, fair enough -- I've added a couple of possible explanations to my answer -- but my point is also quite serious -- you really shouldn't expect to be able to account for things down to the last byte, and that is also kind of the "explanation".
Neil Coffey
Who said "you shouldn't be able to account for things down to the last byte"? This is computer *science*, no cargo cult programming...
foljs
Yeah, but accounting things down to the last byte in a non-deterministic multi-threaded virtual computer with garbage collection is a little impractical.
John Gardner
A: 

When you run with a slightly small size the GC can collect memory from the young/eden/survivor generation and move it into the tenured generation. Allocation for large arrays are made in the tenured generation. Because the GC has previously moved objects into the tenured area it is now has less capacity.

Possibly. It's all down to implementation and timing. Large allocation like this are probably best done through NIO direct allocated buffers.

Tom Hawtin - tackline
A: 

No, there's no insight or truth to be had from the code you posted. You can make that array length go a great deal higher if you increase the max heap space available to you.

One other thing that's worth knowing: calling System.gc() does not mean that the garbage collector runs. It's only a suggestion.

duffymo