As far as I know, when we are creating an ArrayList
:
ArrayList list = new ArrayList(SIZE);
The JVM res
In Java, the referrences to the object are stored in the contiguous memory. The actual objects can stay in a non contiguous manner. So for ex your array might have 10 objects, JVM only needs to reserve the memory for the object references, not the objects. So if each reference takes a Byte(approx not the correct value), but each object takes up a KB, and you have an array of 10 elements, JVm will try to reserve contguous memory of only 1*10 B i.e 10 B. The objects can reside in 10 different memory locations totalling 10KB. Remember that both the contiguous and non contiguous memory spaces are for the memory allocated to the thread.
When it needs to resize the array, the JVM tried to find a contiguos array of the newer length. So if you want to resize the array from 10 to 20 elements, it would try to reserve a contiguous space of 20 KB(using the above example). If it finds this space, it will do a copy of the references from the old array to the new array. If it does not find this space, it will try to do a GC . If it still does not find the space it throws an OutofMemoryException.
Therefore, at any time when you are resizing the array, the JVM needs to find a contiguos memory to store referrences of the new sized array. So if you want to extend the array to a size of say 1000 element, and each reference is a byte each , the JVm will try to find a contiguos memory of 1000* 1KB which is 1 MB. If it finds this memory, it will do a copy of the references, and mark the oldeer contiguos memory for GC , whenever GC runs the next time If it is not able to find the memory , it will try to do a GC, and if it still does not find the contiguos memory , it will throw a Out of memory exception
This is the code in ArrayList which does the resizing. http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/ArrayList.java#ArrayList.ensureCapacity%28int%29
This will throw an OutOfMemoryError
as soon as there is not enough heap space to allocate the new array.
Garbage collection will always be done before this error is thrown. This will compact memory and eliminate all the arrays of smaller sizes that are no longer used. But there is no way to get around the fact that the old array, the new array, and all the contained objects need to all be in memory at once in order for the old contents to be copied into the new list.
So, if your memory limit is 10 MB, and the array takes up 2 MB and is being sized up to 3 MB, and the strings take up 6 MB, then OOM will be thrown even though after this operation you will only have 3 + 6 = 9 MB in memory. One way to avoid this, if you want to run really close to memory limits with a huge array, is to size the array to the full size to begin with so that it never needs to resize.
I assume it will run out of memory since there will be no space to use in the case where JVM can extend array size.
The very first thing I want to correct is, When we are adding new elements into our list, when number of elements reaches 100% of SIZE it reserves a new, contiguous part of memory and copies all of the elements.
New Size of ArrayList will be:
NewSize of ArrayList = (CurrentSize * 3/2) + 1
But going this way is never recommended, if we have idea how much objects needs to be stored then we can use following constructor of ArrayList:-
ArrayList ar = new ArrayList(int initialCapacity);
If our JVM couldn't specify enough contiguous space on heap for the ArrayList, At runtime we'll get
If JVM is not able to allocate requested amount of memory it'll throw
OutOfMemoryError
That's it. Actually JVM memory allocation has only two possible outcomes:
There is no intermediate options, like some amount of memory is allocated.
It has nothing to do with ArrayList, it's a JVM issue. If you asking whether ArrayList somehow manages this situation in a special way - then answer is "No, it does not." It just tries to allocate amount of memory it needs and lets JVM think about the rest.