3

While writing an application that must allocate many objects, I received an exception java.lang.OutOfMemoryError: Java heap space. On reading How to deal with “java.lang.OutOfMemoryError: Java heap space” error (64MB heap size) and java.lang.OutOfMemoryError: Java heap space I tried to run java -jar myJar.jar -Xms1024m -Xmx4096m command, but the application crashes regardless once it allocates about 1.457 GB. This is in 64bit Win XP box. With or w/o -Xmx the moment of crash remains the same in terms of mem usage of java.exe process. Should not a 64 bit application be able to use 4 GB of RAM in a 64 bit OS?

Community
  • 1
  • 1
ajeh
  • 2,652
  • 2
  • 34
  • 65

2 Answers2

3

This is a very complex topic. There is no simple solution as one or two parameters that can avoid OOM. Nonetheless, there are some very useful concepts and techniques we can apply in order to get the problem solved.

In fact, you can perform an initial analysis using a dump file from an OOM, by using argument like -XX:-HeapDumpOnOutOfMemoryError. Your analysis should focus on which part is being used up. Is it the heap, or perm generation? And how your objects in the heap is distributed, like what is the size of the largest object(s)/class(es) when an OOM happens. Tools like MAT is an excellent tool.

  1. OOM could happen in the heap.

    Increase heap size by -Xmx. (It appears this doesn't apply to your case). Yet I would advise you set -Xms to 4G as well so as to see if you do have enough memory and can reserve for your JVM process. If you could still hit OOM then a fragmentation issue could be the reason. This means, after running for a considerable amount of time with memory block allocated and freed, your heap is fragmented and there is no large continuous space for allocation requests for huge objects. For example, if the largest continuous empty space in the heap is 200M - though the total empty space in the heap is 2G - and if your application requests for a large Object, say an array of size 250M, you hit an OOM. Enabling gc logs and employ an GC log analyzer can give you information in this regard. Please also refer to This blog for better understanding and advice on how to avoid fragmentation.

  2. OOM could happen in the perm area.

    Increase perm size by -XX:MaxPermSize=384m. Perm implies the area used for class meta data and static variables. If your application (or the libraries your program uses) loads large amount of classes, or dynamically loads many classes, you might need a larger perm size. If increasing the size doesn't work, you might have leakage in class loading. MAT or memory leak detector should be utilized for investigation then.

Finally, different JVM brands and versions vary in terms of memory structure and parameters. For example, "In JDK 7, interned strings are no longer allocated in the permanent generation of the Java heap, but are instead allocated in the main part of the Java heap (known as the young and old generations), along with the other objects created by the application." So, be sure to check documentation of the version of JDK you are using.

Community
  • 1
  • 1
Alfred Xiao
  • 1,758
  • 15
  • 16
1

You can allocate 64 GB heaps on 64-bit windows with a 64-bit JVM. (Or much larger but I haven't tried)

If you are getting an OutOfMemoryError it means you could not allocate more objects either because

  • you are using more than you think or
  • your memory is heavily fragmented e.g. CMS doesn't defrag the tenured space.

E.g. say you gave no more than 4 KB of continuous memory, and you are using CMS which doesn't defragment the memory and you grow a collection like ArrayList or StringBuidler or HashMap, it cannot allocate the object and thus throws an OutOfMemoryError.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • Neither using more memory than Windows task manager thinks (making a point that it is not me who 'thinks' how much memory is used) nor memory is heavily fragmented. Crash can be avoided if I purposely slow down allocation, for example by introducing heavy disk activity by another process and my Java app has to wait for IO to get object resources. Then memory count goes up further than 1.457 MB and reaches over 2 GB at which point initialization is complete and the app works. To me it sounds like garbage collector not catching up and some JVM bug causing a crash. – ajeh Nov 13 '13 at 18:44