Java memory is limited but it still uses way to much RAM

Solution 1:

In your analysis of the Java memory usage, you forgot the size of the memory used by DirectBuffer's. You can control it with -XX:MaxDirectMemorySize and it defaults to the maximum heap size.

In the worst case scenario, you allow Java to use 342 MiB of memory for its data and some other minor memory zones. You can find the description of all memory zones on Baeldung.

When you start analyzing the real memory consumption, you need to take into account also the size of Java's libraries, which is not huge, but jvm.so accounts for around 20 MiB. All this amounts to the RSS figures you cited.

However, if you want to check if your system can sustain so many JVM's, the intricacies of Linux memory come into play:

  1. RSS accounts for all pages resident in memory, whether they are used for private data of the JVM or cached parts of files and libraries. In a similar way as Java's GC works, the Linux kernel releases the file caches, when it runs shorts of physical memory. Moreover many pages can be shared between JVM's
  2. DATA measures all the private memory mmap-ed into the processes virtual space. Most of it will never have any underlying physical memory.

If you want to check each JVM's virtual memory in detail, use:

pmap -p <processes_pid> -x

or a sorted version on dirty pages:

pmap -p <processes_pid> -x | sort -rnk 4

and you can see what contributes to those RSS and DATA figures.

Edit: You can read more about how Linux classifies memory and the figures given by many tools on this site