Mémoire Java supérieure à 512 mo malgré la configuration -Xmx300m-Xss512k-XX: MétaspaceSize=100M?


J'ai déployé une application java sur Heroku en utilisant les options de machine virtuelle suivantes:

-Xmx300m -Xss512k -XX:MetaspaceSize=100M

Malgré cela, mon application obtient systématiquement Erreur R14 (Quota de mémoire dépassé) erreurs de Heroku. En effet, l'empreinte mémoire atteint 540+mo (et le quota est de 512 mo).

Comment une application java peut-elle prendre plus de 500 mo, alors que je ne lui alloue que 400 mo dans les arguments de la machine virtuelle? Est-ce qu'il me manque un arg VM?

Je m'attendrais à ce que la JVM OOM avant d'atteindre 512 mo de mémoire (mais il augmente juste au-delà des limites que je l'ai définies).

Peut-être que j'ai complètement mal compris comment fonctionnent ces args VM?

Toute aide à ce sujet serait extrêmement appréciée.

Notes:

  • j'utilise java 8
  • Mon procfile est le suivant:

    web: java -Xmx300m -Xss512k -XX:MetaspaceSize=100M -javaagent:./lib/heroku-javaagent-2.0.jar=stdout=true,lxmem=true -Dserver.port=$PORT -Dspring.profiles.active=heroku -cp ./app.jar          org.springframework.boot.loader.JarLauncher
    

Java agent ci-dessus crache les détails suivants dans les journaux:

Dec 13 11:45:54 app/web.1:  measure.mem.jvm.heap.used=177M measure.mem.jvm.heap.committed=212M measure.mem.jvm.heap.max=273M 
Dec 13 11:45:54 app/web.1:  measure.mem.jvm.nonheap.used=129M measure.mem.jvm.nonheap.committed=132M measure.mem.jvm.nonheap.max=0M 
Dec 13 11:45:54 app/web.1:  measure.mem.jvm.direct.used=0M measure.mem.jvm.direct.count=0 measure.mem.jvm.direct.capacity=74M 
Dec 13 11:45:54 app/web.1:  measure.mem.jvm.mapped.used=0M measure.mem.jvm.mapped.count=0 measure.mem.jvm.mapped.capacity=0M 
Dec 13 11:45:54 app/web.1:  measure.mem.linux.vsz=5817M measure.mem.linux.rss=543M 
Author: Tom G, 2017-12-13

1 answers

Comment une application java peut-elle prendre plus de 500 mo, alors que je ne lui alloue que 400 mo dans les arguments de la machine virtuelle? Est-ce qu'il me manque un arg VM?

La JVM a de nombreuses catégories de mémoire: tas, métaspace, piles de threads, cache de code, etc. Il peut même y avoir de la mémoire allouée via JNI que la JVM ne peut pas prendre en compte. Jetez un oeil à ce billet de blog sur la mémoire JVM.

Je m'attendrais à ce que la JVM OOM avant d'atteindre 512 mo de mémoire (mais elle augmente simplement au-delà les limites que j'avais placée).

La plupart des erreurs OOM ne se produisent que lorsque vous manquez d'espace de tas. Dans votre cas, vous avez suffisamment d'espace de tas, mais toutes ces autres catégories vous additionnent et vous exécutent au-dessus de la limite de 512 mo.

Vous pouvez essayer d'abaisser Xmx à -Xmx256m. Tout inférieur à cela et vous commencerez probablement à obtenir des erreurs OOM.

Vous pouvez également inspecter votre code pour détecter les fuites de tampons d'E / S. S'ils ne sont pas fermés correctement, ils peuvent parfois provoquer une mémoire native (hors tas) fuite. Enfin, vérifiez si l'une de vos dépendances (bibliothèques tierces) utilise JNI ou alloue de la mémoire native.

 1
Author: codefinger, 2017-12-13 20:04:48