Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Will I encounter java.lang.OutOfMemoryError even with no lack of memory?

I was reading Unveiling the java.lang.Out OfMemoryError and I was wondering if I've understood it correctly. Is it true that if the Java VM throws a

java.lang.OutOfMemoryError: Requested array size exceeds VM limit

It means that the VM has rejected the creation of an array because it has exceeded a pre-defined limit (exceeded the likes of the VM), and not because I have run out of memory in the heap space?

Am I right to say that java.lang.OutOfMemoryError: Requested array size exceeds VM limit does not indicate a lack of memory?

Even if I have unlimited memory everywhere, the Java VM could still throw a java.lang.OutOfMemoryError: Requested array size exceeds VM limit if it doesn't like my request to create an array of n size?

like image 385
Pacerier Avatar asked Jan 29 '12 12:01

Pacerier


2 Answers

Quoting Troubleshooting Guide for Java SE 6 with HotSpot VM

3.1.3 Detail Message: Requested array size exceeds VM limit (inline bold is mine):

The detail message Requested array size exceeds VM limit indicates that the application (or APIs used by that application) attempted to allocate an array that is larger than the heap size. For example, if an application attempts to allocate an array of 512MB but the maximum heap size is 256MB then OutOfMemoryError will be thrown with the reason Requested array size exceeds VM limit. In most cases the problem is either a configuration issue (heap size too small), or a bug that results in an application attempting to create a huge array, for example, when the number of elements in the array are computed using an algorithm that computes an incorrect size.


UPDATE: encouraged by the @Pacerier I did some quick testing. I wrote a sample program:

public class VmLimitTest {

    public static final int SIZE = 2;

    public static void main(String[] args) throws InterruptedException {
        while(true) {
            byte[] a = new byte[SIZE * 1024 * 1024];
            TimeUnit.MILLISECONDS.sleep(10);
        }
    }
}

And run it with the following JVM options:

-Xms192m -Xmx192m -XX:NewRatio=2 -XX:SurvivorRatio=6 -XX:+PrintGCDetails

This is what they mean:

  • The whole heap is 192 MiB (-Xms192m -Xmx192m)
  • The young generation (eden + survivor) space is 64 MiB, old generation is 128 MiB (-XX:NewRatio=2)
  • Each survivor space (out of two) is 8 MiB, so 48 MiB is left for eden (1:6 ratio, -XX:SurvivorRatio=6)

While testing I discovered the following:

  • If the newly created array can fit into eden (less than 48 MiB), the program runs fine
  • Surprisingly, when the array size exceeds eden size, but can fit into eden and one survivor space (between 48 and 56 MiB), JVM can allocate a single object on both eden and survivor (overlapping two areas). Neat!
  • Once the array size exceeds eden + single survivor (above 56 MiB) the newly created object is placed directly in old generation, bypassing eden and survivor spaces. This also means that suddenly full GC is performed all the time - very bad!
  • I can easily allocate 127 MiB of data but trying to allocate 129 MiB will throw OutOfMemoryError: Java heap space

This is the bottom line - you cannot create an object with size larger than old generation. Trying to do so will result in OutOfMemoryError: Java heap space error. So when can we expect dreadful Requested array size exceeds VM limit?

I tried running the same program with much larger objects. Hitting the array length limit I switched to long[] and could easily go up to 7 GiB. With 128 MiB of max heap declared the JVM was still throwing OutOfMemoryError: Java heap space (!) I managed to trigger OutOfMemoryError: Requested array size exceeds VM limit error trying to allocate 8 GiB in a single object. I tested this on a 32-bit Linux computer with 3 GiB of physical memory and 1 GiB of swap.

That being said you should probably never hit this error. The documentation seems inaccurate/outdated, but it is true in one conclusion: this is probably a bug since creating such huge arrays is very uncommon.

like image 161
Tomasz Nurkiewicz Avatar answered Oct 10 '22 11:10

Tomasz Nurkiewicz


It indicates lack of heap memory. There may be plenty of available memory in other areas but there is not enough heap memory to create requested object (could be array (or) simple string). Here is good blog on this topic .

like image 44
kosa Avatar answered Oct 10 '22 12:10

kosa