19
Fuites mémoires et Collections en Java page : 1/19 ________________________________________________________________________________ COMMENT " REUSSIR " DES FUITES MEMOIRES EN JAVA ? Date Version Modification Author 05/12/08 V1.0 Initial JL PASTUREL ________________________________________________________________________________ memoryLeak Author : Jean-Louis PASTUREL

COMMENT REUSSIR DES FUITES MEMOIRES EN JAVAjean-louis.pasturel.pagesperso-orange.fr/docs/memoryLeak.pdf · La JVM utilisée pour cette démonstration est la JVM HostSpot de SUN 1.6.0_10

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

  • Fuites mémoires et Collections en Java page : 1/19________________________________________________________________________________

    COMMENT " REUSSIR " DES FUITES MEMOIRES EN JAVA ?

    Date Version Modification Author05/12/08 V1.0 Initial JL PASTUREL

    ________________________________________________________________________________memoryLeak Author : Jean-Louis PASTUREL

  • Fuites mémoires et Collections en Java page : 2/19________________________________________________________________________________

    Table des matières 1 INTRODUCTION............................................................................................................................3 2 CLASSES DE TESTS......................................................................................................................3

    2.1 Classe initiale avec fuite mémoire............................................................................................ 3 3 Génération fuite mémoire.................................................................................................................4

    3.1 Lancement application .............................................................................................................4 3.2 Analyse avec Java VisualVM................................................................................................... 4 3.3 Conclusion................................................................................................................................ 6

    4 CORRECTION DE LA FUITE MEMOIRE....................................................................................6 4.1 Source classe corrigée...............................................................................................................6 4.2 Lancement de l’application......................................................................................................7 4.3 Analyse Java VisualVM.......................................................................................................... 8 4.4 Conclusion test NoMemoryLeak1............................................................................................ 9

    5 OUI MAIS AVEC LES WEAKREFERENCE ?............................................................................. 9 5.1 Source classe ............................................................................................................................9 5.2 Lancement de l’application....................................................................................................10 5.3 Analyse Java VisualVM........................................................................................................ 10 5.4 Conclusion test MemoryLeak2 ..............................................................................................13

    6 SOLUTION : java.util.WeakHashMap......................................................................................... 13 6.1 La classe sans fuite mémoire NoMemoryLeak2.....................................................................13 6.2 Lancement de l’application....................................................................................................14 6.3 Analyse Java VisualVM......................................................................................................... 14 6.4 Conclusion test NoMemoryLeak2.......................................................................................... 15

    7 Et si je dé-référence directement la Collection ?............................................................................15 7.1 Source MemoryLeak3.............................................................................................................16 7.2 Lancement de l’application....................................................................................................17 7.3 Analyse Java VisualVM......................................................................................................... 17 7.4 Conclusion test MemoryLeak3...............................................................................................18

    ________________________________________________________________________________memoryLeak Author : Jean-Louis PASTUREL

  • Fuites mémoires et Collections en Java page : 3/19________________________________________________________________________________

    1 INTRODUCTION

    Le but de ce petit document est de montrer comment on peut générer des fuites mémoires en java en utilisant des Collections d’objets.

    La JVM utilisée pour cette démonstration est la JVM HostSpot de SUN 1.6.0_10 sur Windows XP.

    Le suivi d’occupation de la heap sera fait à l’aide de l’outil Java VisualVM fournie avec cette version. L’outil intègre aussi un profiler

    2 CLASSES DE TESTSNous allons nous appuyer sur des classes simples, sans signification fonctionnelle réelle.

    2.1 Classe initiale avec fuite mémoireLa classe principale :

    MemoryLeak.java :import java.util.ArrayList;

    public class MemoryLeak {/** * @param args */public ArrayList listBourrage= new ArrayList(); public void dosomething(String name){

    Bourrage bour=new Bourrage(name);listBourrage.add(bour);// Faire des choses avec bourbour=null; // Ne sert à rien, pour montre seulement que bour est

    bien de-reference;

    }public static void main(String[] args) {

    // TODO Auto-generated method stub// On va creer la fuiteMemoryLeak memLeak=new MemoryLeak();int nbBoucles = Integer.parseInt(args[0]);for ( int i=0;i

  • Fuites mémoires et Collections en Java page : 4/19________________________________________________________________________________

    e.printStackTrace();}

    }}

    }

    La classe auxiliaireBourrage.java :public class Bourrage {// Un simble String

    public String name="monNom" ;public Bourrage(String _name)

    {name=_name;

    }

    }

    3 Génération fuite mémoire

    3.1 Lancement application L’application est lancée avec les paramètres suivants :C:\eclipse\workspace\memoryLeak\bin>java -Xms2M -Xmx2M MemoryLeak 10000000 tttyttttttttytttthhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhttttttttttttttt

    3.2 Analyse avec Java VisualVMLa console Java VisualVM donne :

    ________________________________________________________________________________memoryLeak Author : Jean-Louis PASTUREL

  • Fuites mémoires et Collections en Java page : 5/19________________________________________________________________________________

    Le diagramme en haut à gauche montre l’effet de la fuite mémoire. La mémoire résiduelle après Garbage a tendance à monter au fur et à mesure de la vie de l’application.

    On notera aussi que malgré le paramètre -Xmx à 2Mo la heap de l JVM continue à grandir au delà des 2Mo.

    ________________________________________________________________________________memoryLeak Author : Jean-Louis PASTUREL

  • Fuites mémoires et Collections en Java page : 6/19________________________________________________________________________________

    1 heure après :

    3.3 ConclusionLors d’un dé-référencement d’objet contenu dans une Collection, il faut aussi le retirer

    de la Collection sinon fuite mémoire garantie.L’objet ArrayList garde dans sa collection une seconde Strong Reference de l’objet Bourrage.

    Un objet n’est garbageable que si toutes ses Strong ( Hard) References sont à null.

    4 CORRECTION DE LA FUITE MEMOIRE

    4.1 Source classe corrigéeNoMemoryLeak1.java :import java.util.ArrayList;

    ________________________________________________________________________________memoryLeak Author : Jean-Louis PASTUREL

  • Fuites mémoires et Collections en Java page : 7/19________________________________________________________________________________

    public class NoMemoryLeak1 {/** * @param args */public ArrayList listBourrage= new ArrayList(); public void dosomething(String name){

    Bourrage bour=new Bourrage(name);listBourrage.add(bour);// Faire des choses avec bour

    // ici ce coup-ci on retire bour de la Collection :listBourrage.remove(bour);bour=null; // Ne sert à rien, pour montre seulement que bour est

    bien de-reference;

    }public static void main(String[] args) {

    // TODO Auto-generated method stub// On va creer la fuiteNoMemoryLeak1 noMemLeak=new NoMemoryLeak1();int nbBoucles = Integer.parseInt(args[0]);for ( int i=0;ijava -Xms2M -Xmx2M NoMemoryLeak1 10000000 tttyttttttttytttthhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhttttttttttttttt

    ________________________________________________________________________________memoryLeak Author : Jean-Louis PASTUREL

  • Fuites mémoires et Collections en Java page : 8/19________________________________________________________________________________

    4.3 Analyse Java VisualVM

    Sur ce test, on voit sur le diagramme en haut à gauche qu’il n’y a plus de fuite mémoire car la taille de la mémoire résiduelle après provocation d’un Full GC n’augmente plus.

    Le nombre d’objets Bourrage en vie est aussi réduit par rapport au tir précédent.

    ________________________________________________________________________________memoryLeak Author : Jean-Louis PASTUREL

  • Fuites mémoires et Collections en Java page : 9/19________________________________________________________________________________

    4.4 Conclusion test NoMemoryLeak1La suppression de l’objet Bourrage de la Collection a permis de supprimer la fuite mémoire.

    5 OUI MAIS AVEC LES WEAKREFERENCE ?Pour cet test de la fuite mémoire nous allons utiliser le mécanisme des références faibles

    proposées par Java. Ici nous utiliserons une WeakReference.

    Pour plus d’information en français :

    – http://gfx.developpez.com/tutoriel/java/reference-memoire/

    – http://blog.developpez.com/adiguba?title=comprendre_les_references_en_java

    5.1 Source classe MemoryLeak2.java :import java.lang.ref.WeakReference;import java.util.ArrayList;

    public class MemoryLeak2 {/** * @param args */// La Collection ArrayList ne contient que des WeakReferencepublic ArrayList listBourrage= new

    ArrayList(); public void dosomething(String name){

    Bourrage bour=new Bourrage(name);// Utilisation Avancée// Creation d'une WeakReference sur l'objet bourWeakReference wrBour=new WeakReference(bour);// On met la weakReference dans la collection à la place de la

    Strong ReferencelistBourrage.add(wrBour);// Faire des choses avec bour

    bour=null; // Ne sert à rien, pour montre seulement que bour est bien de-reference

    ;}public static void main(String[] args) {

    ________________________________________________________________________________memoryLeak Author : Jean-Louis PASTUREL

    http://gfx.developpez.com/tutoriel/java/reference-memoire/http://blog.developpez.com/adiguba?title=comprendre_les_references_en_java

  • Fuites mémoires et Collections en Java page : 10/19________________________________________________________________________________

    // TODO Auto-generated method stub// On va creer la fuiteMemoryLeak2 memLeak=new MemoryLeak2();int nbBoucles = Integer.parseInt(args[0]);for ( int i=0;i

  • Fuites mémoires et Collections en Java page : 11/19________________________________________________________________________________

    ________________________________________________________________________________memoryLeak Author : Jean-Louis PASTUREL

  • Fuites mémoires et Collections en Java page : 12/19________________________________________________________________________________

    ________________________________________________________________________________memoryLeak Author : Jean-Louis PASTUREL

  • Fuites mémoires et Collections en Java page : 13/19________________________________________________________________________________

    Le nombre de WeakReference augmente comme lors du premier test avec l’objet Bourrage. .

    5.4 Conclusion test MemoryLeak2 Le remplacement de la référence Strong (Hard) par une référence plus faible sur l’objet dans la Collection ArrayList n’a pas permis d’éliminer la fuite mémoire.L’objet WeakReference a lui même une Strong Reference, on retombe sur le même problème que lors du test initial.

    Je laisse au lecteur le soin de corriger le code en supprimant la Weak référence de la structure ArrayList comme vue lors de la première Collection.Ceci est lié au fait que l’Objet ArrayList ne gère pas le fait que son contenu est de type Reference faible.

    Pour cela, il faut utiliser une autre type de Collection : java.util.WeakHashMap

    6 SOLUTION : java.util.WeakHashMapLa classe java.util.WeakHashMap contient des couples clé/valeur en utilisant des références faibles sur la clé seulement , donc si la clé n'est plus référencée par une référence forte ailleurs dans le programme, le couple est automatiquement supprimé de la collection .

    6.1 La classe sans fuite mémoire NoMemoryLeak2Donc en gérant les référence de Bourrage dans l’objet java.util.WeakHashMap.NoMemoryLeak2.java :

    import java.util.WeakHashMap;

    public class NoMemoryLeak2 {// pour servir de clé à WeakHashMapstatic Long index=0L;/** * @param args */// public ArrayList listBourrage= new ArrayList(); // Remplacement par l'objet java.util.WeakHashMappublic WeakHashMap whmBourrage= new WeakHashMap();public void dosomething(String name){

    Bourrage bour=new Bourrage(name);whmBourrage.put(index,bour);

    ________________________________________________________________________________memoryLeak Author : Jean-Louis PASTUREL

  • Fuites mémoires et Collections en Java page : 14/19________________________________________________________________________________

    index++;// Faire des choses avec bour

    bour=null; // Ne sert à rien, pour montre seulement que bour est bien de-reference

    ;}public static void main(String[] args) {

    NoMemoryLeak2 noMemLeak=new NoMemoryLeak2();int nbBoucles = Integer.parseInt(args[0]);for ( int i=0;ijava -Xms2M -Xmx2M NoMemoryLeak2 10000000 tttyttttttttytttthhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhttttttttttttttt

    ________________________________________________________________________________memoryLeak Author : Jean-Louis PASTUREL

  • Fuites mémoires et Collections en Java page : 15/19________________________________________________________________________________

    6.3 Analyse Java VisualVM

    Le diagramme du haut à gauche montre qu’il n’y a pas de fuite mémoire

    ________________________________________________________________________________memoryLeak Author : Jean-Louis PASTUREL

  • Fuites mémoires et Collections en Java page : 16/19________________________________________________________________________________

    L’historique des objets Bourrage montre qu’il sont bien garbagés ( trait rouge) et ne contribue pas à la fuite mémoire.

    6.4 Conclusion test NoMemoryLeak2L’utilisation de l’objet WeakHashMap permet d’éviter les fuites mémoires sans avoir à supprimer explicitement l’objet dans la Collection.

    7 Et si je dé-référence directement la Collection ?Il s’agit de vérifier que lorsque je positionne à null la référence de l’objet ArrayList, les

    Strong (Hard) Références contenues sont éligibles au garbage.

    7.1 Source NoMemoryLeak4NoMemoryLeak4.java :

    ________________________________________________________________________________memoryLeak Author : Jean-Louis PASTUREL

  • Fuites mémoires et Collections en Java page : 17/19________________________________________________________________________________

    import java.util.ArrayList;

    public class MemoryLeak4 {/** * @param args */public ArrayList listBourrage= new ArrayList(); public void dosomething(String name){

    Bourrage bour=new Bourrage(name);listBourrage.add(bour);// Faire des choses avec bourbour=null; // Ne sert à rien, pour montre seulement que bour est

    bien de-reference;

    }public static void main(String[] args) {

    // TODO Auto-generated method stub// On va creer la fuiteNoMemoryLeak4 noMemLeak=new NoMemoryLeak4();int nbBoucles = Integer.parseInt(args[0]);for ( int i=0;ijava -Xms2M -Xmx2M NoMemoryLeak4 10000000 tttyttttttttytttthhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhttttttttttttttt

    ________________________________________________________________________________memoryLeak Author : Jean-Louis PASTUREL

  • Fuites mémoires et Collections en Java page : 18/19________________________________________________________________________________

    7.3 Analyse Java VisualVM

    Le diagramme du haut à gauche montre que lors des Full Garbage Collector la taille de la mémoire résiduelle revient au même niveau.

    Et en suivant l’historique de la classe Bourrage, on constate bien que les instances sont bien garbagées.

    ________________________________________________________________________________memoryLeak Author : Jean-Louis PASTUREL

  • Fuites mémoires et Collections en Java page : 19/19________________________________________________________________________________

    Les objets Bourrage sont bien garbagés.

    Remarque : Le nom de la classe n’est donc pas correct puisqu’il n’y pas de fuite mémoire. On la renommera NoMemoryLeak4.java

    7.4 Conclusion test NoMemoryLeak4Le dé-référencement d’un objet Collection ( Conteneur) dé-référence les objets qu’il contient .

    ________________________________________________________________________________memoryLeak Author : Jean-Louis PASTUREL

    1 INTRODUCTION 2 CLASSES DE TESTS 2.1 Classe initiale avec fuite mémoire

    3 Génération fuite mémoire 3.1 Lancement application 3.2 Analyse avec Java VisualVM 3.3 Conclusion

    4 CORRECTION DE LA FUITE MEMOIRE 4.1 Source classe corrigée 4.2 Lancement de l’application 4.3 Analyse Java VisualVM 4.4 Conclusion test NoMemoryLeak1

    5 OUI MAIS AVEC LES WEAKREFERENCE ? 5.1 Source classe 5.2 Lancement de l’application 5.3 Analyse Java VisualVM 5.4 Conclusion test MemoryLeak2

    6 SOLUTION : java.util.WeakHashMap 6.1 La classe sans fuite mémoire NoMemoryLeak2 6.2 Lancement de l’application 6.3 Analyse Java VisualVM 6.4 Conclusion test NoMemoryLeak2

    7 Et si je dé-référence directement la Collection ? 7.1 Source NoMemoryLeak4 7.2 Lancement de l’application 7.3 Analyse Java VisualVM 7.4 Conclusion test NoMemoryLeak4