Alocaly Posté(e) 14 décembre 2009 Share Posté(e) 14 décembre 2009 Bonjour à tous, Il m'est arrivé un truc étrange sur mon appli, et je n'arrive pas trop à comprendre... Dans mon appli, j'ai une activity pour le menu, et une autre pour la page de jeu. Dans la création de l'activity de jeu, j'alloue un objet 'dictionnaire', qui alloue un gros buffer de 1.5 Mo ( environ ) et charge dedans mon dictionnaire ( c'est un jeu de lettres ). Et jusqu'à présent, je ne m'en occupais pas plus que ca. Puis en mettant en place un systeme de rapport de crash, je me suis apercu que pas mal de gens crashaient car ils dépassaient la taille mémoire autorisée pour une appli ( 16 Mo ). En analysant plus ce qui se passait, je me suis apercu que lorsqu'on retourne au menu, puis qu'on repart vers la page de jeu, la libération mémoire est plus qu'aléatoire. Et dans certaines conditions que je n'ai pas bien saisi, les allocs se succèdent sans déallocation, et on obtient finalement ce crash... J'ai finalement assez facilement corrigé ce bug : * d'abord en mettant mon dictionnaire comme un singleton de l'appli, * puis, bien plus simplement - pour essayer de comprendre ce qui se passait - en mettant le dictionnaire à null lorsque je quitte l'activity du jeu. Mais ca me fait me poser des questions : Pourquoi je ne peux pas me reposer entièrement sur le garbage collector de Java ?????? * Les activity ne sont pas détruites après le onDestroy ? * le garbage collector attend trop longtemps pour se lancer, et, hop, c'est trop tard ! ( en meme temps, je l'appelais dans la page de menu, et ca n'améliorait pas _du_tout _ les choses...) Je ne suis pas un pro des garbages collectors, mon truc à moi, c'est plutot le C++ où je dois écrire mon propre allocateur pour tout controller, donc je ne sais pas trop quoi conclure...( le C++, ca crash sans doute plus, mais je sais pourquoi... enfin normalement...) Quelqu'un aurait une bonne idée ? Merci pour toute suggestion, Alocaly / Emmanuel Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
Kuiplo Posté(e) 14 décembre 2009 Share Posté(e) 14 décembre 2009 Tu peux forcer le garbage collector avec ca : Runtime r = Runtime.getRuntime(); r.gc(); Perso je fais ça à la fin du chargement de mon jeu, comme ça je suis sûr qu'il ne le fera pas pendant le jeu. Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
Alocaly Posté(e) 15 décembre 2009 Auteur Share Posté(e) 15 décembre 2009 Yep, j'ai essayé ( bon , avec System.gc(), mais j'ai bien l'impression que c'est la même chose ), mais ça ne changeait rien... D'ailleurs la doc indique pour ces deux fonctions que c'est pour proposer à l'OS de lancer la garbage collection, mais qu'il n'y a pas de garantie qu'elle soit faite ! Cela dit, mon probleme mis à part, je pense que c'est une bonne idée de le faire à des moments clé comme tu le fais ! Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
Cyril Mottier Posté(e) 15 décembre 2009 Share Posté(e) 15 décembre 2009 Le garbage collector s'occupe seul de la libération de la mémoire. Ce n'est pas au développeur de dire quand ce dernier doit passer : en clair il n'a aucun contrôle dessus. Le garbage collector passe quand bon lui semble et bloque tout sur son passage .... attention à vos interfaces graphiques ;) Si le garbage collector ne semble pas passer c'est simplement qu'il n'y a pas d'objet désallouable c'est à dire sur lequel aucun autre objet ne pointe (objet lui même non pointé, etc, etc.). Dans ton cas il y a donc n'y a qu'une seule possibilité. Le GC considère qu'il n'y a rien à désallouer (et donc que tu dépasse la taille allouable à force de créer des objets et de conserver des références dessus). Le GC d'Android est loin, trés loin, d'être parfait mais il fonctionne parfaitement. Si il y a une entité à blamer ce n'est certainement pas le GC :) Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
neoakira Posté(e) 16 décembre 2009 Share Posté(e) 16 décembre 2009 En gros, il dit que t'as mal codé :) Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
Alocaly Posté(e) 16 décembre 2009 Auteur Share Posté(e) 16 décembre 2009 Le garbage collector s'occupe seul de la libération de la mémoire. Ce n'est pas au développeur de dire quand ce dernier doit passer : en clair il n'a aucun contrôle dessus. Le garbage collector passe quand bon lui semble et bloque tout sur son passage .... attention à vos interfaces graphiques ;)Si le garbage collector ne semble pas passer c'est simplement qu'il n'y a pas d'objet désallouable c'est à dire sur lequel aucun autre objet ne pointe (objet lui même non pointé, etc, etc.). Dans ton cas il y a donc n'y a qu'une seule possibilité. Le GC considère qu'il n'y a rien à désallouer (et donc que tu dépasse la taille allouable à force de créer des objets et de conserver des références dessus). Le GC d'Android est loin, trés loin, d'être parfait mais il fonctionne parfaitement. Si il y a une entité à blamer ce n'est certainement pas le GC :) Hum... Ok, je comprends bien ca : tant qu'on a des références qui trainent sur notre objet, il ne sera pas détruit. Mais ce qui est troublant, là, c'est que le simple fait de mettre à NULL la référence que j'ai dans mon activity 'Game' sur son ondestroy suffit à résoudre le probleme : ca signifie donc bien que la seule référence qui traine sur ce dictionnaire est mon activité game. De la meme facon, quand je n'avais pas fait d'action pour résoudre ce probleme, la plupart du temps, la mémoire augmentait 'un peu trop', mais exploser la mémoire s'averait plutot compliqué. Donc la déallocation avait bien lieu. Juste pas assez souvent, ou trop tard... Moi je m'attendais donc à ce que, apres onDestroy, l'OS essaye tout seul de détruire l'activity 'Game', et donc mette tout seul ( et assez vite de préférence) cette référence à null, et détruise mon dictionnaire. D'où mon interrogation et ma question. Je ne pensais pas trop à blamer le GC, je suis sur qu'il fait ce qu'il faut, mais je me demandais surtout si il y avait des limites dont je n'avais pas pris conscience. Par exemple, est-ce qu'il serait possible que des activities à moitié détruites trainent en mémoire pendant plus longtemps que je n'aurais pu le croire ( par exemple à cause des toasts, ou que sais-je encore... ) En gros, il dit que t'as mal codé :) :) Ca, mon bon monsieur, c'est bien possible... Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
Cyril Mottier Posté(e) 16 décembre 2009 Share Posté(e) 16 décembre 2009 En gros, il dit que t'as mal codé :) J'ai pas dit ça :) Même si mon explication pouvait peut-être le faire penser ^^ @Alocaly : C'est vrai que le fait de mettre ta référence à null et que le GC libère alors la mémoire est bizarre. Comme ça je n'ai pas de solution mais je persiste sur le fait que le GC marche parfaitement :) Autre petit point, rappelez vous que vous êtes sur des terminaux mobiles et donc contraints :s. La "heap" n'est "que" de 16Mo et donc allouer des dictionnaires de 1,5Mo commence à impacter sérieusement sur l'application (quand on commence à y ajouter le graphique, les Activity, etc.) Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
popolbx Posté(e) 16 décembre 2009 Share Posté(e) 16 décembre 2009 c'est clair....le dictionnaire devrait être en base de données.... non ? Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
Alocaly Posté(e) 17 décembre 2009 Auteur Share Posté(e) 17 décembre 2009 c'est clair....le dictionnaire devrait être en base de données.... non ? Définitivement : NON !!!!! C'est ce que je faisais auparavant, et l'appli était beauuuuuuuuuuucoup trop grosse !! Pour le détail de mes aventures : http://androidblogger.blogspot.com/2009/05/how-to-ship-application-with-pre-baked.html Sinon, j'ai pas grand chose à coté, donc depuis que mis ma référence à null, je suis bien loin des 16 Mo ( aux alentours de 4, ce qui me semble raisonnable ) Emmanuel / Alocaly Citer Lien vers le commentaire Partager sur d’autres sites More sharing options...
Recommended Posts
Rejoignez la conversation
Vous pouvez poster maintenant et vous enregistrez plus tard. Si vous avez un compte, connectez-vous maintenant pour poster.