Slides de la présentation faite à Softshake 2015 ( http://soft-shake.ch )
"Les applications Java (et les autres langages de la JVM) consomment de plus en plus de mémoire, dans le même temps les algorithmes de GC (Garbage Collection) ont amélioré leur efficacité et permettent d’allouer toujours plus de mémoire.
Malheureusement augmenter la RAM pour éviter une OutOfMemoryError sans plus d’investigation conduit souvent à masquer/repousser une fuite mémoire ou un bug applicatif et à générer une nouvelle source d’instabilité pour l’application et la JVM.
Durant cette session nous verrons comment analyser la consommation mémoire d’une application afin de ne pas systématiquement lui accorder plus de mémoire sans savoir quel usage qui en est fait.
Pour cela, nous commencerons par une rapide présentation du fonctionnement de la mémoire de la JVM puis nous verrons comment analyser la mémoire de vos applications en production. Cette deuxième partie sera faite de façon interactive sur une JVM issue d’un retour d’experience à l’aide de l’outil Eclipse Memory Analyzer.
Nous terminerons avec quelques astuces pour vous aider lors de vos futures investigations."
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
G1 (algorithme GC Java 8+)
La JVM d’IBM
Pour des raisons de compréhension, certains mécanismes sont
simplifiés…
Avant propos
5. 5
La plupart des objets ne survivent pas longtemps
Il est plus efficace de rechercher prioritairement les objets à nettoyer
parmi les jeunes objets
Hypothèse générationnelle (Java 1.4+)
nb instances
age / temps
11. 11
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
Des autres Memory Pools
Tenured pour Young
Young pour Tenured
Des ClassLoader
Avec les variables statiques
Quand un objet peut-il être nettoyé ?
La promotion précoce
d’objets en Tenured
provoquera d’autres
problèmes par la suite
12. 12
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
19. 19
La promotion précoce d’objets en Tenured provoquera d’autres
problèmes par la suite
Mettre des références à null aide le collecteur à mieux libérer la
mémoire
En restant raisonnable
Références Cross Memory Pool
20. 20
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
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
21. 21
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
23. 23
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
26. 26
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.
28. 28
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
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;
};