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

avec Java Discussion :

Comment libérer la mémoire alloué a un objet ?


Sujet :

avec Java

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 39
    Points : 29
    Points
    29
    Par défaut Comment libérer la mémoire alloué a un objet ?
    Bonjour à tous .
    Voila , j'utilise un javaBean de portée Session et de type : <ArrayList<Object>> .
    Ce Javabean contient des objets volumineux prenant beaucoup de place en mémoire .
    Je pensais que etant donné que ce javabean etait de portée session , lorsque la session etait terminé (cad lorsque l'utilisateur ferme son navigateur) le javabean etait detruit et libère donc la mémoire qui lui etait allouée ainsi que tous les objets qu'il contenait (puisque dans mon cas , le javabean est un ArrayList<Object> .) .
    Mais en fait il n'en est rien .
    Lorsque je ferme le navigateur , l'occupation mémoire ne baisse pas .
    J'ai donc pensé qu'il fallait attendre le timer de fin de session spécifié dans le fichier web.xml de tomcat et qui est de 30mn .
    Mais au bout de 35 mn apres fermeture du navigateur , rien ne se passe .
    J'ai donc décider de créer un bouton "QUITTER" sur le portail et quand je clique dessus cela appelle le fichier quitter.jsp suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    //monTableau etant mon javabean
    monTableau = null;
    Mais lorsque je clique sur "QUITTER" l'occupation mémoire ne baisse pas , et je n'ai pourtant aucune erreure .

    je tente alors ca :

    Mais ca ne change rien .

    Je ne comprend pas comment faire pour libérer la mémoire et détruire mon javaBean lorsque je n'en ai plus besoin .

    Quelqu'un pourrait m'aider ?

  2. #2
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 39
    Points : 29
    Points
    29
    Par défaut
    Du coup je viens d'essayer ca pour voir :

    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
    20
    21
    22
    <%@page import="java.util.ArrayList"%>
    <%
    	out.println("Mémoire utilisée :" + (((Runtime.getRuntime().totalMemory()/1024)/1024)*100)/((Runtime.getRuntime().maxMemory()/1024)/1024)+"%<br>") ;
     
    	ArrayList<String> monTableau = new ArrayList<String>();
     
    	for (int i = 0 ; i < 80000000 ; i++)
    	{
    		monTableau.add("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
    	}
    	out.println("Tableau rempli<br>");
     
    	out.println("Mémoire utilisée :" + (((Runtime.getRuntime().totalMemory()/1024)/1024)*100)/((Runtime.getRuntime().maxMemory()/1024)/1024)+"%<br>") ;
     
    	out.println("VIDAGE<br>");
     
    	monTableau.clear();
    	monTableau = null;
    	System.gc();
     
    	out.println("Mémoire utilisée :" + (((Runtime.getRuntime().totalMemory()/1024)/1024)*100)/((Runtime.getRuntime().maxMemory()/1024)/1024)+"%<br>") ;
    %>
    ET le resultat est :
    Mémoire utilisée :0%
    Tableau rempli
    Mémoire utilisée :83%
    VIDAGE
    Mémoire utilisée :86%

  3. #3
    Expert confirmé
    Avatar de slim_java
    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2008
    Messages
    2 272
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2008
    Messages : 2 272
    Points : 4 539
    Points
    4 539
    Par défaut
    la gestion de la mémoire est prise en charge par le ramasse-miette.
    mais il est possible d'invoquer le garbage collector avec


  4. #4
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par techz Voir le message
    Je pensais que etant donné que ce javabean etait de portée session , lorsque la session etait terminé (cad lorsque l'utilisateur ferme son navigateur) le javabean etait detruit et libère donc la mémoire qui lui etait allouée ainsi que tous les objets qu'il contenait (puisque dans mon cas , le javabean est un ArrayList<Object> .) .
    Mais en fait il n'en est rien .
    Lorsque je ferme le navigateur , l'occupation mémoire ne baisse pas .
    La session d'une application web n'est pas détruite à la fermeture du navigateur ! Le serveur ne peut pas savoir le moment où le navigateur est fermé.

    La session est conservé pendant un certain temps depuis la dernière action de l'utilisateur. C'est pourquoi il faut éviter de stocker n'importe quoi en session...


    Citation Envoyé par techz Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    //monTableau etant mon javabean
    monTableau = null;
    S'il s'agit d'un bean en session il faut le supprimer de la session avec removeAttribute().

    Citation Envoyé par techz Voir le message
    Je ne comprend pas comment faire pour libérer la mémoire et détruire mon javaBean lorsque je n'en ai plus besoin .
    Il suffit de ne plus conserver de référence en session ni dans le scope application (ni en static !!!). Le GC se chargera de tout cela au moment opportun !

    Toutefois tu ne verras pas de changement instantanément ! En effet le GC peut regrouper les libérations pour optimiser la gestion de la mémoire.
    Mieux : si l'occupation mémoire de l'OS n'est pas trop important, il peut conserver cette espace mémoire afin de le réutiliser plus tard, en considérant que si ton application a utilisé beaucoup de mémoire, elle risque d'en avoir encore besoin...



    a++

    PS : Ne te base pas sur Runtime pour surveiller la mémoire, mais utilise plutôt un outils de monitoring comme jconsole...

    Et ne surtout pas invoquer directement le GC ! A moins que tu ne veuilles plomber les performances de ton application...

  5. #5
    Membre habitué
    Profil pro
    Étudiant
    Inscrit en
    Avril 2007
    Messages
    133
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2007
    Messages : 133
    Points : 149
    Points
    149
    Par défaut
    C'est le garbage collector qui s'occupe de libérer la mémoire. En mettant à null la reference vers ton objet, le GC saura que tu n'utilises plus cet objet. Ainsi, lorsque ta mémoire sera saturée, le garbage collector videra l'espace mémoire utilisé par cet objet, puisqu'il n'y aura plus aucune référence qui pointera vers l'objet.

    Laisses le GC faire son travail en gros... s'il ne libère pas l'espace mémoire de l'objet, c'est que le programme n'a pas besoin de plus de mémoire. Lorsqu'il en aura par contre besoin, le GC videra l'espace mémoire.

    Des posts interessants sur le GC ou l'analyse de l'empreinte mémoire des programmes :

    http://blog.xebia.fr/2008/03/12/gc-g...ge-first-jdk7/
    http://http://blog.xebia.fr/2008/11/...oire-dune-jvm/

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 39
    Points : 29
    Points
    29
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Salut,

    S'il s'agit d'un bean en session il faut le supprimer de la session avec removeAttribute().
    ..
    Ok , donc si je fait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    session.removeAttribut("monTableau");
    Lorsque le gc aura besoin de libérer de la mémoire , il pourrat utiliser l'espace qui etait allouer a mon bean ?
    Même si la session de mon utilisateur n'est pas terminée ?

  7. #7
    Membre chevronné
    Inscrit en
    Août 2009
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 1 073
    Points : 1 806
    Points
    1 806
    Par défaut
    Oui, à la condition que ton tableau ne soit référencé nulle part ailleurs. En particulier, pas via un autre objet mis en Session, dans un formulaire qui trainerait, etc. ^^

  8. #8
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 39
    Points : 29
    Points
    29
    Par défaut
    Si je fais un :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    session.removeAttribut("monTableau");
    juste avant que l'utilisateur ne ferme se session , c'est bon non ?
    Il n'y aura de toute facon plus aucunes references puisque le navigateur est fermé .

    Certes , il y a aura d'autre monTableau qui existent , mais ils sont dans d'autres session pour d'autres utilisateurs , donc ca ne pose pas de problème ? ce n'est pas la même instance ...

  9. #9
    Membre chevronné
    Inscrit en
    Août 2009
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 1 073
    Points : 1 806
    Points
    1 806
    Par défaut
    Je dis juste que ton tableau peut avoir été utilisé dans d'autres classes, par exemple des classes globales, et de là on pourrait avoir une référence qui resterait vivante quelque part. Pour ça il faut connaître le code
    Mais en assumant que nulle part ailleurs ce tableau n'est référencé, alors effectivement il devient éligible pour le gc, et donc tu n'as plus à t'en soucier.

  10. #10
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Par curiosité : que contient "monTableau", et pourquoi as-il besoin d'être stocké en session ???

    a++

  11. #11
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 39
    Points : 29
    Points
    29
    Par défaut
    En fait mon Tableau contient le resultat de différentes requetes passées a une bdd.
    J'ai besoin de les mettre en session pour qu'ils soient accessible tous le long de la session d'un utilisateur afin qu'il puisse faire des traitements dessus .
    J'ai pensé a serializer sur le disque dur , mais le problème c'est que cela devient incomfortable pour l'utilisateur , car c'est trop long , le volume de données est tres important : plusieurs Giga par resultats.(Oui j'ai bcp de mémoire sur mon serveur ^^)

    Sinon j'aurais une question pour les pros (surtout pour voir si j'ai bien compris) :
    Le gc s'execute dans un thread de manière asynchrone , ce qui fait qu'on ne peut savoir a quel moment il va s'executer.
    Sauf si on passe a la JVM le parametre -noasyncgc et que l'on appelle System.gc() dans le code .
    Lorsque le GC fait son travail, il execute la methode finalize des objets non referencés (celle de la classe mère Object si notre propre classe ne possede pas de finalize) puis libère la mémoire alloué a cet objet .
    Dans le cadre de J2EE et d'un serveur tomcat , lorsqu'un utilisateur appelle une page jsp , tout les objets de cette même page sont crées lors de la construction de la page html par le serveur puis une fois que la page html est envoyé au client , tous les objets de cette page jsp sont eligible au GC puisqu'ils ne sont plus reférencés ? c'est bien ca ?
    Bien sur si cette page contient des javaBean qui ont une portée session ou application , je suppose que ceux-ci ne sont eligible et reste en mémoire entre les différente pages .

    Merci d'avance de vos éclaircissements .

  12. #12
    Membre chevronné
    Inscrit en
    Août 2009
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 1 073
    Points : 1 806
    Points
    1 806
    Par défaut
    Citation Envoyé par techz Voir le message
    Le gc s'execute dans un thread de manière asynchrone , ce qui fait qu'on ne peut savoir a quel moment il va s'executer.
    Sauf si on passe a la JVM le parametre -noasyncgc et que l'on appelle System.gc() dans le code .
    Attention, quand tu fais -noasyncgc autant que je sache tu zappes simplement les appels automatiques faits par la JVM au gc. De toute façon, quand tu utilises System.gc(), tu ne fais que solliciter l'appel au gc, il n'y a pas de garantie que ça soit fait immédiatement.
    Pour le reste, ok

  13. #13
    Expert éminent sénior
    Avatar de Baptiste Wicht
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    7 431
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2005
    Messages : 7 431
    Points : 21 324
    Points
    21 324
    Par défaut
    Citation Envoyé par techz Voir le message
    Sauf si on passe a la JVM le parametre -noasyncgc et que l'on appelle System.gc() dans le code
    Cette option est encore supportée mais est ignorée depuis Java 1.2. Si tu essaies, tu devrais avoir un warning disant que l'option n'est plus supportée. Elle est juste encore là pour des raisons de compatibilités, mais cela ne va rien changer.

  14. #14
    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
    plusieurs gigas pour la session utilisateur?!? Je doute que, meme en une journée, un user puisse traiter et modifier un Giga de données, ce qui me laisse à penser que tu ferais mieux de revoir la manière dont tu gères tes objets en mémoire. Il y a visiblement beaucoup de déchets.

    Quand au GC: laisse le faire son boulot. Les variables qui ne sont plsu référencées seront nettoyées à temps.

  15. #15
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par techz Voir le message
    J'ai besoin de les mettre en session pour qu'ils soient accessible tous le long de la session d'un utilisateur afin qu'il puisse faire des traitements dessus .
    J'ai pensé a serializer sur le disque dur , mais le problème c'est que cela devient incomfortable pour l'utilisateur , car c'est trop long , le volume de données est tres important : plusieurs Giga par resultats.(Oui j'ai bcp de mémoire sur mon serveur ^^)
    Je serait curieux de savoir ce que tu manipules précisément, et pourquoi tu ne peux pas te contenter d'exécuter la bonne requête lorsqu'il le faut uniquement.

    Citation Envoyé par techz Voir le message
    Lorsque le GC fait son travail, il execute la methode finalize des objets non referencés (celle de la classe mère Object si notre propre classe ne possede pas de finalize) puis libère la mémoire alloué a cet objet .
    La méthode finalize() peut retarder la libération de l'objet, car si elle est redéfini cela force le GC à revérifié que l'objet ne soit pas "revenu à la vie"...

    Citation Envoyé par techz Voir le message
    Dans le cadre de J2EE et d'un serveur tomcat , lorsqu'un utilisateur appelle une page jsp , tout les objets de cette même page sont crées lors de la construction de la page html par le serveur puis une fois que la page html est envoyé au client , tous les objets de cette page jsp sont eligible au GC puisqu'ils ne sont plus reférencés ? c'est bien ca ?
    Bien sur si cette page contient des javaBean qui ont une portée session ou application , je suppose que ceux-ci ne sont eligible et reste en mémoire entre les différente pages .
    C'est bien ca !
    La durée de vie de la session dépend de la configuration du serveur, et de la dernière action de l'utilisateur (à moins de la détruire explicitement).
    Le scope application reste quand à lui vivant pendant toutes l'exécution du serveur (il faut donc éviter d'y mettre n'importe quoi).


    Citation Envoyé par Rei Ichido Voir le message
    De toute façon, quand tu utilises System.gc(), tu ne fais que solliciter l'appel au gc, il n'y a pas de garantie que ça soit fait immédiatement.
    Et dans le meilleur des cas le GC ignorera complètement l'appel (d'ailleurs on peut forcer cela avec l'option -XX:+DisableExplicitGC).
    L'appel explicite au GC n'est généralement pas une bonne solution, car cela génèrera un full-GC c'est à dire une vérification de tous les objets, ce qui peut être assez couteux en temps...

    Il est préférable de laisser le GC se débrouiller seul ! De toute manière si la mémoire vient vraiment à manquer il fera la full-GC de lui même...

    a++

Discussions similaires

  1. Comment libérer la mémoire allouée au OleVariant ?
    Par LeBigornot dans le forum API, COM et SDKs
    Réponses: 6
    Dernier message: 10/01/2010, 09h11
  2. Comment libérer la mémoire tampon
    Par xmeszeus dans le forum Fortran
    Réponses: 4
    Dernier message: 20/11/2008, 09h29
  3. Réponses: 3
    Dernier message: 05/04/2007, 14h56
  4. Libérer la mémoire allouée à un objet
    Par boudou dans le forum Langage
    Réponses: 6
    Dernier message: 21/02/2006, 22h25
  5. Comment libérer la mémoire d'un TList ?
    Par Tchaill39 dans le forum Langage
    Réponses: 8
    Dernier message: 16/11/2005, 17h53

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