2. 2
ANALYSE DE JVM LIVE
Agenda
2
ANALYSE DE DUMP
3
PRINCIPES DE GESTION DE MÉMOIRE EN JAVA1
TAKE AWAY4
3. 3
Cette présentation est focalisée sur OpenJdk, les notions
présentées restent cependant valables pour la JVM d’IBM
Pour des raisons de compréhension, certains mécanismes sont
simplifiés…
Avant propos
4. 4
Principes de gestion de mémoire en Java
Hypothèse générationnelle
Rappels
Les variations entre les versions de JVM
Déterminer qu’un objet est libérable
6. 6
Tous les objest sont alloués sur la heap
Pas d’allocation dans la stack, que des références
Chaque thread possède une thread local areas
Permet les allocations sans synchronisation
Sauf pour les objets de grande taille
Un objet ne peut pas être désaloué explicitement
C’est le GC – ou ramasse-miettes qui est en charge de ça
Allocations
7. 7
Lorsqu’il n’est plus référencé (indirectement) par une racine (‘root’)
Il n’est plus possible d’obtenir une référence sur cet objet
Java n’utilise pas un mécanisme de compteur de références
Il n’y a pas de fuite mémoire technique possible
Quand un objet peut-il être nettoyé ?
9. 9
La plupart des objets ne survivent pas longtemps
Il est plus efficace de rechercher prioritairement les objets à nettoyer
parmi les jeunes objets
Les références des vieux objets vers les récents sont (relativement) peu
nombreux
Hypothèse générationnelle (Java 1.4+)
nb instances
age / temps
16. 16
Les ‘strong references’ sont des ‘pointeurs’
Object a = b;
object.attribut = c
Mais aussi les autres types de référence (java.lang.ref.Reference)
SoftReference, WeakReference, and PhantomReference
Références
17. 17
Lorsqu’il n’est plus référencé (indirectement) par une racine (‘root’)
Java n’utilise pas un mécanisme de compteur de références
Il n’y a pas de fuite mémoire technique possible
Les racines sont constituées de tout ce qui permet d’atteindre un objet :
Des piles d’appels (stack)
Des registres CPU
Des références JNI
Classes chargées par le SystemClassLoader
Des autres Memory Pools
Tenured pour Young
Young pour Tenured
Quand un objet peut-il être nettoyé ?
25. 25
La promotion précoce ou inutile d’objets en Tenured
provoquera d’autres problèmes par la suite
Cela va faire augmenter les références entre la old génération et la
young, ce qui est contraire aux hypothèses générationnelles
Mettre des références à null peut aider le collecteur à mieux libérer
la mémoire
En restant raisonnable
Références Cross Memory Pool
26. 26
Un GC survient
Lors d’un échec d’allocation
La mémoire est pleine
La mémoire est trop fragmentée pour la taille souhaitée
La mémoire atteint un seuil pour certain algorithme ( ≃92% pour CMS)
Un appel explicite à System.gc() (C’est le mal !)
QQQ sun.rmi.dgc.client.gcInterval and sun.rmi.dgc.server.gcInterval.
Lors d’un GC, on parcours le graph des objets référencés par toutes
les racines
Un partie de ce parcours est bloquant (stop-the-world)
Le SWAP de JVM durant un stop-the-world est dramatique
Fonctionnement - sommaire - des algorithmes Java
27. 27
Le parcours de toutes les racines n’est pas efficace pour un Young GC
Ne passe pas l’échelle lorsque la taille de la JVM augmente
On utilise un mécanisme de ‘dirty cards’ pour limiter le parcours de la
mémoire
Fonctionnement - sommaire - des algorithmes Java
0 reference card0
Eden S0 S1 Tenured
B A
0 0 0 0 0 0 0 0 0 0
512bytes
0 reference card0
Eden S0 S1 Tenured
B A
0 0 0 0 0 0 0 0 0
512bytes
01 0
29. 29
Java 6 (6u45)
Décembre 2006 à Février 2013 (fin des mises à jour)
Java7 (7u80)
Juillet 2011 à Avril 2015
Java8 (8u60)
Mars 2014 à Septembre 2017 (?)
Java9
> Avril 2016
Les versions Java
30. 30
Serial GC
Parallel GC
Parallel Old GC (Parallel Compacting GC)
Concurrent Mark & Sweep GC (or "CMS")
Garbage First (G1) GC
Les algorithmes en jdk 7/8
31. 31
Remplacement de la PermGen par le MetaSpace
Similaire à JRockit et IBM
Décommissionnement PermGen (commencé en Java7)
MetaSpace en Native Memory => plus de limitation de taille
Le flag –XX:PermSize disparait
Introduction de G1 (Garbage-First Garbage)
Orienté faible pause STW (+6Go et moins 500ms de pause)
G1 fait de la défragmentation (compaction)
CMS reste toujours meilleur pour les petites JVM
Par défaut à partir de Java 9 (JEP 248)
En Java 8
34. 34
Monitorer vos JVM
Live
Analyser vos traces GC
Analyser a posteriori l’évolution de la mémoire et des GC
Analyser vos dumps mémoire
Comprendre ce qui remplit votre JVM au runtime
Démo
35. 35
JConsole ou VisualVM
Monitoring distant
jdk/bin/jstatd -J-Djava.security.policy=security.policy
Demo Live Monitoring
grant codebase "file:${java.home}/../lib/tools.jar" {
permission java.security.AllPermission;
};
38. 38
-verbose:gc
-Xloggc:/var/log/elasticsearch/gc.log
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=3
-XX:GCLogFileSize=200M
-XX:+PrintGCDetails
-XX:+PrintTenuringDistribution
-XX:+PrintGCCause
-XX:+PrintGCApplicationStoppedTime
Ce sont des paramètres de production
Analyse :
• http://www.hp.com/go/java (free)
• https://github.com/chewiebug/GCViewer (free)
• http://www.jclarity.com/censum/ (payant)
Demo - Log GC
39. 39
Dump en cas d’OutOfMemory
-XX:+HeapDumpOnOutOfMemoryError
Si vous avez des soucis avec la mémoire de vos JVM faites des
heapdumps avant de les éteindre
sudo jmap -dump:file=memory.hprof -F $pid
Pour diminuer le temps de freeze de la JVM
sudo gcore -o jvm.hprof $pid ç bloquant mais rapide
sudo jmap -J-d64 -dump:live,file=jvm.hprof /usr/bin/java /tmp/jvm.core
http://blogs.atlassian.com/2013/03/so-you-want-your-jvms-heap/
x
Dump mémoire
40. 40
Dominator Tree
An object x dominates an object y if every path in the object graph
from the start (or the root) node to y must go through x.
The immediate dominator x of some object y is the dominator
closest to the object y.
42. 42
Pas d’optiomisation a priori
“Premature optimization is the root of all evil”
Measure Don’t Guess
Remettez vos habitudes en question
Les JVM ont évolué, des paramêtres utilisés sur de vieux Jdk n’ont plus de raison d’être
Exemple : -Xms != -Xmx
Mettez à jour vos JVM
Mettez en place le monitoring distant
jdk/bin/jstatd -J-Djava.security.policy=security.policy
Activer les traces sur vos JVM
Log GC
-Xloggc:logs/gc-`date '+%Y%m%d-%H%M'`.log
-XX:+PrintGCDetails -XX:+PrintTenuringDistribution
-XX:+PrintGCCause -XX:+PrintGCApplicationStoppedTime
-Xloggc:/var/log/elasticsearch/gc.log
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=3
-XX:GCLogFileSize=200M
Analyse avec http://www.hp.com/go/java (free) ou http://www.jclarity.com/censum/ (payant)
-XX:+HeapDumpOnOutOfMemoryError
Faites des heapdumps avant d’éteindre vos JVM
sudo jmap -dump:file=memory.hprof -F $pid
Take away
grant codebase "file:${java.home}/../lib/tools.jar" {
permission java.security.AllPermission;
};