Why the Operating System Says It Can't Allocate Memory to Jvm When It Has Enough Memory

Why the operating system says it can't allocate memory to jvm when it has enough memory

It seems you have overcommit disabled:

vm.overcommit_memory = 2

And the amount of currently allocated memory on the system has almost reached the limit. You can see it in /proc/meminfo section of the crash log:

CommitLimit:    15951192 kB
Committed_AS: 15837036 kB

The solution is to enable heuristic overcommit handling:

sudo sysctl vm.overcommit_memory=0

or to increase overcommit ratio:

sudo sysctl vm.overcommit_ratio=100

For more information see overcommit-accounting and man 5 proc.

What happens when the JVM runs out of memory to allocate during run time?

-Xmx just defines the maximum size of the heap. It makes no guarantee on wether there is so much memory or not. It only ensures that the heap will never be bigger then the given value. That said, Option B.) will happen, an outOfMemoryError will be thrown.

Understanding JVM Memory Allocation and Java Out of Memory: Heap Space


How does the JVM actually allocate memory for itself?

For the heap it allocate one large continuous region of memory of the maximum size. Initially this is virtual memory however, over time it becomes real memory for the portions which are used, under control of the OS

How does this relate to how the OS communicates available memory to the JVM?

The JVM has no idea about free memory in the OS.

Or more generally, how does memory allocation for any process actually work?

In general it uses malloc and free.

How does virtual memory come into play?

Initially virtual memory is allocated and this turns into real memory as used. This is normal for any process.

Let's say you have a system with 32GB of physical memory and you allocate all 32GB to your Java process.

You can't. The OS need some memory and there will be memory for other purposes. Even within the JVM the heap is only a portion of the memory used. If you have 32 GB of memory I suggest as 24 GB heap max.

Let's say that your process actually consumes all 32GB of memory,

Say you have 48 GB and you start a process which uses 32 GB of main memory.

how can we enforce the process to use virtual memory instead of running into OOM exceptions?

The application uses virtual memory right from the start. You cannot make the heap too large because if it starts swapping your machine (not just your application) will become unusable.

You can use more memory than you have physical by using off heap memory, carefully. However managed memory must be in physical memory so if you need a 32 GB heap, buy 64 GB of main memory.

JVM sending back memory to OS

To control return of heap to the OS, from Java 5 onward, use the -XX:MaxHeapFreeRatio option, as described in the tuning guide.

If you feel your question is meaningfully different from this one, please point out how.

How to deal with java.lang.OutOfMemoryError: Java heap space error?

Ultimately you always have a finite max of heap to use no matter what platform you are running on. In Windows 32 bit this is around 2GB (not specifically heap but total amount of memory per process). It just happens that Java chooses to make the default smaller (presumably so that the programmer can't create programs that have runaway memory allocation without running into this problem and having to examine exactly what they are doing).

So this given there are several approaches you could take to either determine what amount of memory you need or to reduce the amount of memory you are using. One common mistake with garbage collected languages such as Java or C# is to keep around references to objects that you no longer are using, or allocating many objects when you could reuse them instead. As long as objects have a reference to them they will continue to use heap space as the garbage collector will not delete them.

In this case you can use a Java memory profiler to determine what methods in your program are allocating large number of objects and then determine if there is a way to make sure they are no longer referenced, or to not allocate them in the first place. One option which I have used in the past is "JMP" http://www.khelekore.org/jmp/.

If you determine that you are allocating these objects for a reason and you need to keep around references (depending on what you are doing this might be the case), you will just need to increase the max heap size when you start the program. However, once you do the memory profiling and understand how your objects are getting allocated you should have a better idea about how much memory you need.

In general if you can't guarantee that your program will run in some finite amount of memory (perhaps depending on input size) you will always run into this problem. Only after exhausting all of this will you need to look into caching objects out to disk etc. At this point you should have a very good reason to say "I need Xgb of memory" for something and you can't work around it by improving your algorithms or memory allocation patterns. Generally this will only usually be the case for algorithms operating on large datasets (like a database or some scientific analysis program) and then techniques like caching and memory mapped IO become useful.



Related Topics



Leave a reply



Submit