Libération de mémoire qui ne se fait pas...

Libération de mémoire qui ne se fait pas... - Java - Programmation

Marsh Posté le 01-01-2005 à 18:15:15    

Bonjour !
 
Je suis entrain de devenir fou avec le garbage collector de java et l'impossibilité de faire un free à la main...
 
Depuis que j'ai intégré le mode client / serveur dans mon projet, la mémoire augmente inexorablement au cours de l'exécution. Le problème vient à priori des requètes qu'il ne libère pas après les avoir envoyé et lu.
 
Le code d'envoi de requete du serveur :
 

Code :
  1. public void envoyerRequeteSituation() throws Exception {
  2. CRequeteSituation requeteSituation = new CRequeteSituation(
  3.  OPartieServeur.getInstance().getCarte().toString(),
  4.  OPartieServeur.getInstance().getListePacmansEnvoyable(),
  5.  OPartieServeur.getInstance().getListeFantomesEnvoyable()
  6.  );
  7.  m_outputStream.writeObject(requeteSituation);
  8.  m_outputStream.flush();
  9. }


 
Le constructeur utilisé :
 

Code :
  1. public CRequeteSituation(String matriceBlocs,
  2.     List<CPersonnageEnvoyable> listePacmans,List<CPersonnageEnvoyable> listeFantomes) {
  3.         m_matriceBlocs = matriceBlocs;
  4.         m_listePacmans = listePacmans;
  5.         m_listeFantomes = listeFantomes;
  6.     }


 
En gros, les méthodes toString et getListe créent respectivement un new String ou new LinkedList, les remplissent puis les return.
 
Si j'ai bien compris le principe du garbage collector, ces string et liste n'étant (à priori) référencés que par la requete (et par une variable locale dans les toString et getListe, mais qui logiquement sont détruites à la fin de la fonction), à la fin de envoyerRequete, il devrait libérer requeteSituation et tout ce qu'elle contient.
 
Or ce n'est pas le cas, les données stagnent quelque part, où et pourquoi je ne sais pas... J'ai tenté de mettre un requeteSituation = null à la fin de la fonction, aucun résultat (logique...), j'ai tenté de ne faire qu'une fois le new CRequeteSituation() en mettant cette requete en donnée membre du serveur et en utilisant dans envoyerRequete() une fonction integrer() avec exactement le mm code que le constructeur, mais ça ne marche plus (pb avec la serialization et les références je suppose).
 
Bref quelqu'un aurait une solution pour libérer des choses à la main, ou verrait immédiatement l'erreur dans mon sale code de noob ? :( Merci d'avance... :jap:

Reply

Marsh Posté le 01-01-2005 à 18:15:15   

Reply

Marsh Posté le 01-01-2005 à 18:25:08    

fais pêter tout le code.
 
 
mais sache une chose : si tu avais fait un free, tu aurais déclenché un bug.


---------------
trainoo.com, c'est fini
Reply

Marsh Posté le 01-01-2005 à 18:26:28    

hum et donne-nous les chiffres de consomation mémoire et les arguments passés à la JVM stp ...


---------------
trainoo.com, c'est fini
Reply

Marsh Posté le 01-01-2005 à 19:24:01    

Pas d'arguments spéciaux utilisés (pas que je sache du moins, à noter que j'utilise netBeans...).
 
Conso mémoire : ça commence à 40Mo et au bout de 10mn de jeu en gros, ça atteind 90Mo et ça bug...
 
J'ai oublié de dire que j'avais fait un test pour être sûr que l'augmentation mémoire venait des requètes : j'ai envoyé les requètes à une fréquence 10 fois inférieure, et le problème ne se posait effectivement plus (même s'il aurait sûrement réapparu après une centaine de minutes).
 
Le reste du code qui peut jouer :
 
La fonction toString :
 

Code :
  1. public String toString() {
  2.         String tmp = "";
  3.        
  4.         for (int i = 0; i < m_matriceBlocs.length; i++)
  5.             for (int j = 0; j < m_matriceBlocs[i].length; j++)
  6.                 tmp  += m_matriceBlocs[i][j] + ":";
  7.         return tmp ;
  8. }


 
Fonction getList :
 

Code :
  1. public List<CPersonnageEnvoyable> getListePacmansEnvoyable() {
  2.         List<CPersonnageEnvoyable> resListe = new LinkedList();
  3.        
  4.         for (CPacman p : m_listePacmans) {
  5.             resListe.add(p.getEnvoyable());
  6.         }
  7.        
  8.         return resListe;
  9.     }


 
getEnvoyable() renvoit un newCPersonnageEnvoyable qui contient les données à envoyer du Pacman.
 
Et la récupération de la requete côté client :
 

Code :
  1. CRequeteSituation requeteLue;
  2. requeteLue = (CRequeteSituation) m_inputStream.readObject();
  3. OPartieClient.getInstance().setCarte(requeteLue.getMatriceBlocs());
  4. OPartieClient.getInstance().refreshListePacmans(requeteLue.getListePacmans());
  5. OPartieClient.getInstance().refreshListeFantomes(requeteLue.getListeFantomes());


 
Le setCarte n'alloue rien, il écrase les données de l'ancienne matrice par les nouvelles, idem pour les refresh qui écrasent les anciennes données des personnages par les nouvelles.


Message édité par Luigi le 01-01-2005 à 19:24:50
Reply

Marsh Posté le 01-01-2005 à 19:26:49    

je te demande pas ce TU penses qui pourrait jouer, si tu avais trouvé le pb, tu ne serais pas là, mais je te demande de tout nous montrer pour que NOUS évaluions la chose.


---------------
trainoo.com, c'est fini
Reply

Marsh Posté le 01-01-2005 à 20:25:59    

Ben en même temps je me vois mal mettre les 61 classes ici ;) Donc autant que possible je met les parties de code qui sont susceptibles de poser problème (pouvoir localiser le problème n'implique pas de savoir le résoudre).
 
Je viens de tester en + de ne plus envoyer de requete, de faire simplement
 

Code :
  1. public void envoyerRequeteSituation() throws Exception {
  2. OPartieServeur.getInstance().getCarte().toString();
  3. OPartieServeur.getInstance().getListePacmansEnvoyable();
  4. OPartieServeur.getInstance().getListeFantomesEnvoyable();
  5. }


 
C'est à dire exactement la même chose qu'avant (les appels à getCarte et getListe à la même fréquence), mais sans envoyer de requète. Et là, la mémoire est stable.
 
Donc je pense vraiment que ça vient de ces requetes que java ne libère pas pour une raison inconnue, et il ne libère donc pas non plus leur contenu (le string et les listes). Reste à savoir pourquoi...

Reply

Marsh Posté le 01-01-2005 à 20:39:20    

et c'est le mosieur sur le forum de Sun qui gagne une tringle à rideaux :
quand on fait de la sérialisation d'objets on est obligé de garder l'ensemble des objets passés dans le stream pour gérer les références circulaires.
 
donc soit tu fais risette, soit tu fermes le stream quand tu n'en a plus besoin, mais il faut vider cette collection.


---------------
trainoo.com, c'est fini
Reply

Marsh Posté le 01-01-2005 à 21:26:52    

Pis ta fonctions toString elle doit fabriquer des centaines vorie des milliers d'objet, faudrait voir à utiliser un StringBuffer plutôt :o

Reply

Marsh Posté le 01-01-2005 à 21:37:13    

En fait en pratique j'utilise un stringBuilder, la différence de perf avec un string est impressionante :ouch: (pourquoi stringBuilder je ne sais pas, c'est pas moi qui ai codé cette partie en fait - le réseau non plus d'ailleurs, c'est un projet en groupe de 7). Mais bon c'est clair que ça doit pas être optimisé du tout, on débutait tous en java.
 
Quoiqu'il en soit entre temps j'ai réglé le problème, effectivement avec un reset :
 

Code :
  1. m_outputStream.writeObject(requeteSituation);
  2. m_outputStream.flush();
  3. m_outputStream.reset();


 
M'en vais taper sur les doigts à celui qui a fait le réseau qui me l'a livré avec deux semaines de retard pour bien tout étudier en profondeur et résultat il n'a pas géré cette subtilité  :pfff: :o  
 
Merci pour l'aide en tout cas ;)  :hello:


Message édité par Luigi le 01-01-2005 à 21:38:01
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed