IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Interfaces Graphiques en Java Discussion :

PB Memoire - Coup de Gueule


Sujet :

Interfaces Graphiques en Java

  1. #21
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par AxanOrg Voir le message
    Il est dit que dès lors qu'une référence existe sur un objet, celui-ci n'est pas collectable par le GC. Et ce y compris si 2 objets se référencent entre eux, mais ne sont eux-même référencé par aucuns autres.
    C'est faut. Le garbage collector n'a aucun problème avec les références cyclique. Il faut qu'il existe un chemin de hard références depuis une zone non nettoyable (stack, classes, threads, frames visibles, sockets réseau actives, etc). deux objets qui se référencent mutuellement sans être référencé ailleurs seront nettoyés.
    Citation Envoyé par AxanOrg Voir le message
    Qu'en est t'il des variables "final" ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    void maMethodeDeMaClasseA()
    {
      final Object monObjFinal = new Object();
      this.monAttributDeMaClasseAQuiAdmetUnListenerXXX.addXXXListener(new XXXListener()
      {
        void onCeciCela(Event e)
        {
           // Que se passe t'il si j'utilise une reference final dans mon inner class ?
           System.out.println("Obj: "+monObjFinal.toString());
     
           // Que se passe t'il si j'utilise un attribut de l'instance contenante dans mon inner class !?
           System.out.println("monAttributDeMaClasseA: "+monAttributDeMaClasseA.toString());
     
           // Que se passe t'il si j'utilise une méthode de mon instance contenante dans mon inner class !!?
           maMethodeDeMaClasseA();
        }
       });
    }
    En lui même le mot clé final n'a pas beaucoup d'influence. Ce qui en as, c'est ce que tu fait de la variable après. Dans ton cas, tu la référence depuis une inner class, celle-ci lors de sa construction recevra alors copie de la référence. Tant que l'instance de cette inner class ne sera pas collectable, à la fois l'instance de ta classe entourante ne le sera pas (l'inner class référence d'office l'instance de la outer class, sauf si elle est static), et l'instance de Object ne le sera pas.

    Le listener sera garbage collectable lorsque monAttributDeMaClasseAQuiAdmetUnListenerXXX le sera. Celui là même, a priori, le sera quand MaClasseA le sera (sauf si tu référence aussi l'attribute ailleurs). Donc tout se résumera, a priori, au déréférencement de ton instance de MaClasseA

  2. #22
    Membre habitué Avatar de donnadieujulien
    Développeur informatique
    Inscrit en
    Avril 2008
    Messages
    433
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2008
    Messages : 433
    Points : 191
    Points
    191
    Par défaut Confirmer
    Bonjour, je suis confronté au même problème que vous, dans una application d'environ 50 classes, qui gère une BDD en client serveur.

    Au début, j'était directment à plus de 60Mo de mémoire utilisée dès l'éxécution du programme.

    En fait ca venait des images... j'en avait une 20aines, icones, fonds...

    Et la je passe directement à 1Mo!!!!

    Par contre, le problème que je n'ai pas encore résolu, c'est en rapport avec les communications BDD.

    La au début c'était la cata, avec 5000 ou 1000 lignes d'une table à récupérer et un algorithme pas au point (ex : un Resultset déclaré sur une classe et pas dans la méthode), j'avais des fuites de mémoire de fou!!!!
    Je montait en 10 secondes à 500Mo.

    En optimisant, j'en suis à 50-100 Mo max (+ les images)

    Mais je constate que petit à petit, centaine de kilo octet par centaine de kilo octets, la mémoire utilisée augmente, et je ne comprends pas pourquoi...

    LE garbage collector n'y fait rien.

    Mais je pense que la JVM est concue de tele facon que la mémoire n'es tpas vidée instantanément au cas ou on doivent se resservir des infos, même si la classe est "dispose" ou finalize. Moi en tous cas si je l'avais concu j'aurais fait comme ca, pour gagner du temps, ca permet de pas réecrire la ram tt le temps.

    Mais bon, ca n'explique pas pourquoi la mémire, utilisée augmente petit à petit.

    Est ce que ca peut venir d'un objet statique, duquel je me resservirai plusieurs fois, et donc que son allocation mémoire soit toujours de plus en plus grande?
    On ne peut créér ce qu'on ne peut imaginer...
    Tu sens la puissance du BIT?

  3. #23
    Futur Membre du Club
    Inscrit en
    Juillet 2006
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 10
    Points : 5
    Points
    5
    Par défaut
    Effectivement même si le GC collecte les objets, il ne rend pas forcément la mémoire à l'OS (donc on ne vois pas forcément la mémoire utilisée diminuer dans le gestionnaire des taches).

    Les références static ne posent soucis que si l'objet qu'elle référence a une durée de vie plus courte que la référence elle même. Dans ce cas la référence empèche de collecter l'objet pourant devenu inutile.

    Dans mon cas j'avais fait le tri parmis mes classes pour voir lesquelles utilisaient des listener, et j'ai remplacé les références sur les listener par des WeakReference. Je n'ai pas très bien compris comment utiliser les WeakReference, car dans mon cas elles se trouvaient aussitôt créé, aussitôt collectées.. mais en tout cas j'ai pu observer que mon soucis me fuite mémoire venait bien des classes en questions et du fait des références maintenues sur les listeners.

    Si qq'un peut m'expliquer simplement comment devrait t'on utiliser les WeakReference dans ce cas:

    j'ai l'habitude de souvent créer les listener en tant que classe anonyme en même temps que je les enregistre.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    monObjetListenable.addXXXListener(new MonInterfaceListener() {/*implementation classe anonyme..*/});
    Si bien que personne d'autre que monObjetListenable ne garde de référence sur mon listener (et effectivement, aucun autre objet n'en a besoin).
    Cependant si je le référence avec une WeakReference, alors celle-ci est aussitôt collectée (normal) et je perd aussitôt mon listener..
    Je ne saisie pas trop comment on est sensé utiliser les WeakReference dans ce cas là ?

  4. #24
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    normalement, si tu utilise des weakreferences comme listeners, t'es censé garder une référence après l'appel, pour éviter son gc. On utilise typiquement dans ce genre de situation:



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    public class MaClasse extends UnTruc implements UnListener{
     
        //....
     
        unObject.addXXXXListener(this);
    }
    tant que l'instance de MaClasse sera utilisée, "unObjet" la notifiera de changements qui surviennent.

  5. #25
    Rédacteur
    Avatar de eclesia
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    2 108
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 108
    Points : 3 203
    Points
    3 203
    Par défaut
    Citation Envoyé par natha Voir le message
    - éviter les variables statiques d'objets
    ...
    - catcher les RuntimeException
    Je ne suis pas d'accord avec ses deux la.
    - L'utilisation des variables static fournit des objects qui vont etre réutilisé souvent, Il preferable d'avoir un object constant pour tout le monde que N instance d'objet. Bien sur il ne faut pas en abuser. mais ce n'est pas une mauvaise pratique en soi.

    - Si on en vient a catcher les runtime exceptions c'est qu'il a de gros soucis avec le fonctionnement de l'application, ca ressemble plus a un patch de derniere minute qu'une vrai pratique. La question que je me pose aussi, c'est "Ou peux tu bien utiliser ce catch efficacement ?". Le faire au moment d'une methode qu'on sait volumineux en cout memoire ? c'est inutile, la methode pourrais tres bien marcher et faire un OutOfMemory si une toute petite methode qui suit.

    Je rajoute quelques conseil :
    - Utiliser des classes immutables. ces classes peuvent etre utilisé beaucoup plus souvent qu'on ne le pense et permet d'avoir des objets dont le comportement et parfaitement previsible et donc simplifi grandement les divers soucis qu'on peut se faire avec la gestion memoire.
    - Essayer d'utiliser d'avantage les fabrique/service, ces objets sont generalement des singletons thread safe qui on un cout memoire permanent mais faible comparé a la creation de N instances.
    - Eviter de creer des objets inutiles pour les methodes.
    Par exemple vous avez une liste et vous voulez la remplir avec d'autres listes venant d'autres objects.
    Plutot que d'avoir une methode :
    utilisez plutot une methode du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void fillTrucs(List<Truc> malist);
    L'objet voit qu'on lui fournit une liste a remplir, il n'aura pas besoin d'en créé une.
    L'idéale est d'avoir ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    List<Truc> getTrucs(List<Truc> maList);
    L'objet créera une list si on passe une liste null, sinon il remplira celle fournie.
    Il y a plein de petite choses du genre qui permettent de grapiller pas mal d'espace memoire et enormement de performances.
    Systèmes d'Informations Géographiques
    - Projets : Unlicense.science - Apache.SIS

    Pour un monde sans BigBrother IxQuick ni censure RSF et Les moutons

  6. #26
    Futur Membre du Club
    Inscrit en
    Juillet 2006
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 10
    Points : 5
    Points
    5
    Par défaut
    - L'utilisation des variables static fournit des objects qui vont etre réutilisé souvent
    C'est justement parceque rien ne le garantie que je disais qu'elles sont à éviter.
    Si l'on est sûr à 100% que l'objet référencé en static sera de longue durée de vie, pas de soucis, mais il faut éviter d'utiliser des variables static sans être sûr de la durée de vie des objets qu'elles référenceront.

    Concernant l'utilisation de singlethon plutôt que l'instantiation de plusieurs objets, je ne vois pas où est le problème, ou du moins, c'est hors-sujet si l'on parle des FUITES mémoire.
    Du moment que les objets sont de courte durée de vie, et qu'une fois inutilisés ils sont correctement collectés, celà ne pose pas de problème d'espace mémoire que d'en créer massivement (même si ça n'est peut être pas le plus optimisé, mais d'un point de vue 'FUITE MEMOIRE' ça ne pose aucun soucis).
    La question est justement, comment s'assurer que nos objets soient correctement collectés, qu'elles sont les bonnes pratiques à avoir.
    Je n'ai pas le sentiment d'avoir reçu de réponse satisfaisante (claire, exhaustive, fiable) pour l'instant.

  7. #27
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par eclesia Voir le message
    - Eviter de creer des objets inutiles pour les methodes.
    Par exemple vous avez une liste et vous voulez la remplir avec d'autres listes venant d'autres objects.
    Plutot que d'avoir une methode :
    utilisez plutot une methode du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void fillTrucs(List<Truc> malist);
    L'objet voit qu'on lui fournit une liste a remplir, il n'aura pas besoin d'en créé une.
    L'idéale est d'avoir ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    List<Truc> getTrucs(List<Truc> maList);
    L'objet créera une list si on passe une liste null, sinon il remplira celle fournie.
    Autant je suis d'accord sur éviter des créer de gros objets inutiles, autant je ne suis pas d'accord avec ton exemple . Il comporte à mon sens plusieurs problèmes:

    1) Notation non 'javabean', ce qui implique que la méthode sera inutilisable dans des contexte type Expression Language (entre autres)
    2) non intuitif (on a tendance à rechercher dans l'api un getter , pas un filler), mais çà c'est une question de convention sur le projet j'imagine aussi
    3) aucun gain en instantiation. Ce que tu gagne en ne faisant pas un new ArrayList(taille), tu le perd sur le redimensionnement d'array que fait une arraylist lorsque sont tableau est plein.
    4) Une ArrayList occupe peu de mémoire par rapport à la mémoire qu'occupe les objets qu'elle contient.

  8. #28
    Rédacteur
    Avatar de eclesia
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    2 108
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 108
    Points : 3 203
    Points
    3 203
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    Autant je suis d'accord sur éviter des créer de gros objets inutiles, autant je ne suis pas d'accord avec ton exemple . Il comporte à mon sens plusieurs problèmes:

    1) Notation non 'javabean', ce qui implique que la méthode sera inutilisable dans des contexte type Expression Language (entre autres)
    2) non intuitif (on a tendance à rechercher dans l'api un getter , pas un filler), mais çà c'est une question de convention sur le projet j'imagine aussi
    3) aucun gain en instantiation. Ce que tu gagne en ne faisant pas un new ArrayList(taille), tu le perd sur le redimensionnement d'array que fait une arraylist lorsque sont tableau est plein.
    4) Une ArrayList occupe peu de mémoire par rapport à la mémoire qu'occupe les objets qu'elle contient.
    1) Il n'y a aucune obligation d'etre 100% javaBean... si un get/set ne se prete pas a le methode que l'on veut avoir, alors je ne vais pas me forcer a en mettre un get.
    2) la javadoc est la pour ca.
    3) Si son tableau n'est pas plein ou si des valeurs sont deja presente on y gagne.
    4) peut etre peu de memoire, mais un peu de memoire quand meme.

    C'est vrai que le "fillTruc" on le voit jamais (c'etait juste a titre d'exemple).
    On peut trouver beaucoup d'exemple dans les classes Java2D et autre relative au math.
    Exemple : AffineTransform
    Methode :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    public Point2D inverseTransform(Point2D ptSrc, Point2D ptDst) 
              Inverse transforms the specified ptSrc and stores the result in ptDst.
    Ce que je voulais dire dans tout ca, c'est qu'il y beaucoup de facon de reduire le nombres de references qui se baladent. Moins de references c'est moins de boulot pour le GC, moins de risques de fuite memoire et tres souvent un gain en performance.
    Systèmes d'Informations Géographiques
    - Projets : Unlicense.science - Apache.SIS

    Pour un monde sans BigBrother IxQuick ni censure RSF et Les moutons

Discussions similaires

  1. [Coup de gueule] Appel à la modération.
    Par r0d dans le forum Politique
    Réponses: 74
    Dernier message: 18/07/2006, 15h18
  2. Réponses: 1
    Dernier message: 31/05/2006, 11h27

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo