If you caught OutOfMemoryError, this does not mean that your application creates many objects that cannot be cleaned by the garbage collector and fill all the memory you have allocated with the -Xmx parameter. At a minimum, I can think of two other cases where you can see this error. The fact is that the java process memory is not limited to the -Xmx area, where your application programmatically creates objects.

')
The memory area occupied by the java process consists of several parts. The type OutOfMemoryError depends on which of them did not have enough space.
1. java.lang.OutOfMemoryError: Java heap space
There is not enough space in the heap, namely, in the memory area in which objects that are created programmatically in your application are placed. The size is set by the -Xms and -Xmx parameters. If you are trying to create an object, and there is no space left in the heap, then you get this error. Usually, the problem lies in the memory leak, of which there is a great many, and the Internet is simply replete with articles on this topic.
2. java.lang.OutOfMemoryError: PermGen space
This error occurs when there is insufficient space in the Permanent area, the size of which is specified by the parameters -XX: PermSize and -XX: MaxPermSize. What is there and how to deal with OutOfMemoryError arising there, I have already described in great detail
here .
3. java.lang.OutOfMemoryError: GC overhead limit exceeded
This error may occur as if the first and second areas overflow. It is connected with the fact that the memory is low and the GC is constantly working, trying to free up some space. This error can be disabled using the -XX parameter: -UseGCOverheadLimit, but, of course, it should not be disabled, and either solve the problem of memory leakage, or allocate more volume, or change the GC settings.
4. java.lang.OutOfMemoryError: unable to create new native thread
I first encountered this error a few years ago when I was doing load testing and trying to figure out the maximum number of users who can work with our web application. I used a special tool that allowed users to login and emulate their standard actions. On a certain number of clients, I started getting OutOfMemoryError. Without really reading the text of the message and thinking that I do not have enough memory to create a user session and other necessary objects, I increased the size of the application heap (-Xmx). What was my surprise when after that the number of users simultaneously working with the system only decreased. Let's take a closer look at how this happened.
In fact, it is very easy to reproduce on windows on a 32-bit machine, since there no more than 2GB are allocated to the process.
Suppose you have an application with a large number of simultaneous users, which runs with the parameters -Xmx1024M -XX: MaxPermSize = 256M -Xss512K. If 2G is available for the whole process, then 768M is still free. It is in this remaining memory that the stack of threads is created. Thus, approximately you can create no more than 768 * (1024/512) = 1536 (I managed to create 1316 with such parameters) threads (see the picture at the beginning of the article), after which you will get an OutOfMemoryError. If you increase -Xmx, then the number of threads you can create is correspondingly reduced. The option with a decrease of -Xss, to be able to create more threads, is not always an option, since you may have threads requiring quite large stacks in the system. For example, the initialization thread or some background tasks. But there is a way out. It turns out when programmatically creating a thread, you can specify the size of the stack:
Thread (ThreadGroup group, Runnable target, String name, long stackSize) . Thus, you can set -Xss to be quite small, and actions requiring large stacks, run in separate streams created using the above-mentioned constructor.
In more detail, what lies in the stack of the thread, and where this memory goes, you can read
here .
Of course, this problem may seem a bit contrived to you, since most of the servers now rotate on a 64-bit architecture, but I still find this example very useful, as it helps to figure out what parts the java-process memory consists of.