GNU/Linux >> Tutoriels Linux >  >> Linux

Utilisation croissante de la mémoire résidente (RSS) du processus Java

J'ai rencontré le même problème. C'est un problème connu avec la glibc>=2.10

Le remède consiste à définir cette variable d'environnement export MALLOC_ARENA_MAX=4

Article IBM sur la configuration de MALLOC_ARENA_MAXhttps://www.ibm.com/developerworks/community/blogs/kevgrig/entry/linux_glibc_2_10_rhel_6_malloc_may_show_excessive_virtual_memory_usage?lang=en

Recherchez MALLOC_ARENA_MAX sur Google ou recherchez-le sur SO pour trouver de nombreuses références.

Vous voudrez peut-être également régler d'autres options de malloc pour optimiser une faible fragmentation de la mémoire allouée :

# tune glibc memory allocation, optimize for low fragmentation
# limit the number of arenas
export MALLOC_ARENA_MAX=2
# disable dynamic mmap threshold, see M_MMAP_THRESHOLD in "man mallopt"
export MALLOC_MMAP_THRESHOLD_=131072
export MALLOC_TRIM_THRESHOLD_=131072
export MALLOC_TOP_PAD_=131072
export MALLOC_MMAP_MAX_=65536

Il est également possible qu'il y ait une fuite de mémoire native. Un problème courant est les fuites de mémoire native causées par la non fermeture d'un ZipInputStream /GZIPInputStream .

Une façon typique qu'un ZipInputStream est ouvert par un appel à Class.getResource /ClassLoader.getResource et appeler openConnection().getInputStream() sur le java.net.URL instance ou en appelant Class.getResourceAsStream /ClassLoader.getResourceAsStream . Il faut s'assurer que ces flux sont toujours fermés.

Certaines bibliothèques open source couramment utilisées ont eu des bogues qui fuient java.util.zip.Inflater non fermés ou java.util.zip.Deflater instances. Par exemple, la bibliothèque Nimbus Jose JWT a corrigé une fuite de mémoire associée dans la version 6.5.1. Java JWT (jjwt) avait un bogue similaire qui a été corrigé dans la version 0.10.7. Le modèle de bogue dans ces 2 cas était le fait que les appels à DeflaterOutputStream.close() et InflaterInputStream.close() ne pas appeler le Deflater.end() /Inflater.end() quand un Deflater /Inflater instance est fournie. Dans ces cas, il ne suffit pas de vérifier le code pour les flux en cours de fermeture. Tous les Deflater /Inflater les instances créées dans le code doivent gérer ce .end() est appelé.

Une façon de vérifier les fuites de Zip*Stream est d'obtenir un vidage de tas et de rechercher des instances de n'importe quelle classe avec « zip », « Inflater » ou « Deflater » dans le nom. Ceci est possible dans de nombreux outils d'analyse de vidage de tas tels que Yourkit Java Profiler, JProfiler ou Eclipse MAT. Cela vaut également la peine de vérifier les objets en état de finalisation car, dans certains cas, la mémoire n'est libérée qu'après la finalisation. Il est utile de vérifier les classes susceptibles d'utiliser des bibliothèques natives. Cela s'applique également aux bibliothèques TLS/ssl.

Il existe un outil OSS appelé leakchecker d'Elastic qui est un agent Java qui peut être utilisé pour trouver les sources de java.util.zip.Inflater instances qui n'ont pas été fermées (.end() pas appelé).

Pour les fuites de mémoire native en général (pas seulement pour les fuites de bibliothèque zip), vous pouvez utiliser jemalloc pour déboguer les fuites de mémoire native en activant le profilage d'échantillonnage malloc en spécifiant les paramètres dans MALLOC_CONF variables d'environnement. Des instructions détaillées sont disponibles dans cet article de blog :http://www.evanjones.ca/java-native-leak-bug.html . Ce billet de blog contient également des informations sur l'utilisation de jemalloc pour déboguer une fuite de mémoire native dans les applications Java. Il existe également un article de blog d'Elastic mettant en vedette jemalloc et mentionnant leakchecker, l'outil qu'Elastic a mis en open source pour détecter les problèmes causés par les ressources de gonflage zip non fermées.

Il existe également un article de blog sur une fuite de mémoire native liée à ByteBuffers. Java 8u102 a une propriété système spéciale jdk.nio.maxCachedBufferSize pour limiter le problème de cache décrit dans ce billet de blog.

-Djdk.nio.maxCachedBufferSize=262144

Il est également bon de toujours vérifier les descripteurs de fichiers ouverts pour voir si la fuite de mémoire est causée par une grande quantité de fichiers mmap:ed. Sous Linux lsof peut être utilisé pour lister les fichiers ouverts et les sockets ouverts :

lsof -Pan -p PID

Le rapport de la carte mémoire du processus pourrait également aider à enquêter sur les fuites de mémoire native

pmap -x PID

Pour les processus Java exécutés dans Docker, il devrait être possible d'exécuter la commande lsof ou pmap sur "l'hôte". Vous pouvez trouver le PID du processus conteneurisé avec cette commande

docker inspect --format '{{.State.Pid}}' container_id

Il est également utile d'obtenir un vidage de thread (ou d'utiliser jconsole/JMX) pour vérifier le nombre de threads puisque chaque thread consomme 1 Mo de mémoire native pour sa pile. Un grand nombre de threads utiliserait beaucoup de mémoire.

Il existe également un suivi de la mémoire native (NMT) dans la JVM. Cela peut être utile pour vérifier si c'est la JVM elle-même qui utilise la mémoire native.

L'outil jattach peut également être utilisé dans un environnement conteneurisé (docker) pour déclencher des threaddumps ou des heapdumps à partir de l'hôte. Il est également capable d'exécuter des commandes jcmd nécessaires au contrôle de NMT.


Linux
  1. Utilisation de la mémoire Linux

  2. Comment vérifier l'utilisation de la mémoire du processus avec la commande Linux pmap

  3. Linux - Limiter l'utilisation de la mémoire pour un seul processus Linux ?

  4. Utilisation élevée de la mémoire mais aucun processus ne l'utilise

  5. Représentation graphique de l'utilisation de la mémoire des processus sous Linux

Outil qui permet la journalisation de l'utilisation de la mémoire ?

Utilisation maximale de la mémoire d'un processus Linux/Unix

Utilisation de la mémoire du processus en cours en C

Invoquer et suivre l'utilisation de la mémoire d'un processus

Déterminer correctement l'utilisation de la mémoire sous Linux

Ubuntu Linux :traiter la mémoire d'échange et l'utilisation de la mémoire