A Java process basically consists of two different heap spaces.
- The Java heap (new, old and perm space)
- And the so called native C heap.
The above is often confusing when it comes to OutOfMemory errors and allocation failures. In particular in 32-bit mode where the overall process space is limited to 4gb or even 2gb depending on the OS.
As mentioned before, the total process size in 32-bit mode is limited to 4gb maximum. Java heap and C heap combined, along with other spaces, e.g. for libraries, threads etc. cannot exceed this 4gb limit. So if you increase the Java heap, e.g. by increasing -Xmx/-Xms from 1.5gb to 2.5gb this will have a significant side effect on the C-heap. Before the increase, the C-heap could easily grow as big as 2gb. Since there were 4gb -1.5gb = 2.5gb left. AFTER the increase of the Java heap from 1.5gb to 2.5gb we have only 4gb – 2.5gb = 1.5gb left for all the other spaces. Including the C-heap.
Unfortunately it is entirely application dependent how big the Java heap and the C heap need to be. While the size of the Java heap can be configured explicitly, this cannot be done for the C-heap. C-heap simply expands until the process size reaches the 4gb limit. So care must be taken if you configure the Java heap too big. This can and will result in allocation failures of the C-heap. E.g. messages such as this one typically mean, that the C-heap was exhausted:
java.lang.OutOfMemoryError: requested 67108872 bytes for Chunk::new. Out of swap space?
Please note the C++ syntax with the double colons. Or this one:
# There is insufficient memory for the Java Runtime Environment to continue. # Native memory allocation (malloc) failed to allocate 65544 bytes
In both cases C-heap was too small. A solution would have been to decrease the Java heap. Yes, to decrease! This would have given the C-heap more room to expand. On the other hand, we still can hit the classic Java.lang.OutOfMemoryErrors. Those clearly point towards insufficient Java heap capacity.
As you can see, if you operate in 32-bit mode there can be a conflict between Java and C-heap, which might not be easy to solve. If all fails then consider moving to 64-bit, where the 4gb process size limit will no longer be an issue. Background information: The Hotspot Java virtual machine (JVM) itself is written in C++. Hence all JVM internal allocations take place solely in the C-heap. For example when the GC kicks in to collect dead objects in the Java heap, it will allocate space in the native heap to perform its work.
On the other hand, all Java objects that are being allocated by a Java program will end up in the Java heap. The C-heap will not be touched.