Jump to content

Rendre de la mémoire à l'OS : comment ?


bsegonnes

Recommended Posts

Bonjour,

Cà fait longtemps que j'ai rien demandé. Voici mon problème (mais d'autres peuvent être concernés :-) )

Mon appli utilise un lib externe assez grosse (code+resources). Bien qu'ayant fait un peut de ménage, çà reste énorme (8-9Mo). Ca va me prendre des mois à petit à petit bien optimiser un code que je connais pas (en faisant d'autres améliorations en // bien sûr).

Le problème : il peut arriver qu'un utilisateur charge un fichier un peut gros, et mon applie se retrouve 'vite' en Out Of Memory (16Mo).

J'intercepte, stoppe le chargement, met qques variables à null, gc(), runFinalization(), met un joli message.

L'utilisateur quitte ensuite l'Activity pour revenir à celle derrière.

Mon applie utilise toujours 16Mo à ce moment. J'ai donc de temps en temps des crash en cliquant sur 'Menu', logs OOF, ou impossible d'allouer images lorsque je scrolle dans les listes, ...

Mon applie n'utilise plus les 16Mo pourtant.

Comment indiquer à l'OS qu'il peut récupérer un peut de RAM ?

PS : gc() : libère des objets non utilisés, mais la RAM prise par ceux-ci reste allouée à l'applie.

PS 2: c'est une partie de cette RAM inutilisé par mon applie que je voudrais rendre.

Merci

Link to comment
Share on other sites

Lorsque tu alloue de la mémoire en java, la taille du Heap de VM peut augmenter si nécessaire. La VM alloue alors de la mémoire système. Si tu dé-référence des objets, puis que le GC passe, la mémoire système n'est pas désalouée, la taille du Heap java reste donc le même, MAIS à l'intérieur du Heap il y a de la place disponible. Cette place sera alors utilisée pour les objets que tu créera par la suite.

Dans ton cas, j'ai l'impression qu'il y a une fuite mémoire...

Essai de monitorer ce qui se passe avec

Par exemple tu créé un Thread (avec setDaemon(true)) au lancement de ton application, et toute les 5 secondes tu log les infos mémoire.

Par exemple :

Thread t = new thread(new runnable() {
 public void run() {
Log.d("MEMORY", "free=" + Runtime.getRuntime().freeMemory());
Log.d("MEMORY", "max=" + Runtime.getRuntime().maxMemory());
Log.d("MEMORY", "total=" + Runtime.getRuntime().totalMemory());
 }
});
t.setdaemon(true);
t.start();

Je n'ai jamais essayé sur android, mais ça devrait fonctionner.

Link to comment
Share on other sites

Dans Logcat, je vois bien les gc(), la mémoire est bien rendue au 'heap'.

Je quitte ma 2em Activity pour revenir à la 1er (çà devrait encore libérer de la RAM ?)

Puis :

Le problème c'est que certains trucs (lors apparition menu -> crash, ou autre trucs interne à l'OS quand on scrolle dans une liste : erreurs OOM dans logcat, mais pas de crash) utilisent la mémoire du systeme et pas de l'applie.

Si dans ma 2em Activity je charge de 'petits' fichiers ne provoquant pas de OOF : je peux bien sur ouvrir mes menus, etc... C'est bien un probème de RAM.

J'utilise OS 1.6 ....

J'enverrais des logs ce soir.

Je sais que l'on ne peux par rendre de la RAM à l'OS (même en C). Il faut quiter l'applie pur cela.

Mais on sait jamais... il y a peut-être une manip/commande spéciale sur Android (due à l'aspet embarqué/limité par rapport à une JVM normale).

Link to comment
Share on other sites

j'ai eut ce probleme dans une applie, je l'ai résolu mais la méthode risque de ne pas fonctionner si le dépassement est vraiment gros.

en fait he chargeais des images dans une activity B en arrivant d'une activity A.

je quittait cette activity, et dans la principale j explosais en en chargeant d'autres.

j'ai donc fait une sorte de Factory statique pour la gestion de ces images.

ma factory est une classe "statique" qui charge les images dans une collection statique (oui c'est crado).

Donc là c'est pire que tout car en quittant l activité B la mémoire n'est pas vidée.

Sauf que sur le retour de A je nettoie ma collection.

Et toute l'astuce réside dans le fait que la collection est une collection de SoftReference.

Un post sur le blog dev android rappelle l'utilité de ces objets. En gros si le systeme a besoin de heap il commence à se servir

dans les softReference en les mettant à la poubelle :)

Si tu en as re besoin, tu as une propriété qui te permet de savoir qu'elle est morte et tu recharge l'objet.

Bon évidement si un seul objet provoque ça c'est mort.

mais je suppose que le traitement de ton gros fichier donne naissance à plein d'objets ..hein ?

Link to comment
Share on other sites

Merci poplbx, le problème c'est que j'ai récupéré dans mon applie des sources (lecture PDF, office, ...) que je ne maitrise pas.

Au plus je peut optimiser suivant cette 'stratégie' : mettre de final, supprimer variables inutiles, supprimer logs, mettre en commentaire des méthodes dont le nom m'inspire (couleurs, etc). Sinon, je ne touche pas au code !

Je ne maitrise pas non plus ce que mes utilisateurs vont vouloir charger !!!

Donc : impossible de faire des factory ou autre :-(

Link to comment
Share on other sites

Après avoir intercepté proprement le OOF, et quitté mon Activity : j'ouvre Menu (OK), et quand je clique dessus : lors de l'ouverture d'une Dialog (Activity n'affichant pas de bitmap de ma part)

java.lang.OutOfMemoryError : bitmap size exeeds VM budget

Sinon, il m'arrive de charger sans problème un gros fichier. Pas d'OOF. Je quitte l'Activity , bouton Menu et !

VM won't let us allocate 2304 bytes

InflateException : Binary XML file ...

Ce qui me donne espoir ce sont les logs tels que :

dalvikvm-heap Clamp target GC heap from 16.184MB to 16.000MB

Je voudrais bien en provoquer moi-même des 'Clamp' en baissant à 12MB par ex... :-)

Link to comment
Share on other sites

Je reste persuadé qu'il s'agit d'une fuite mémoire.

A Vérifier :

- que les bitmaps non utilisés sont bien libérés avec un bitmap.recycle()

- que les java.nio.Buffer sont bien mis à null

- qu'il n'y a pas de list, map ou array en static qui garde un gros paquets de datas en cache (dans ce cas utiliser des WeakReference ou des SoftReference comme l'a dis popolbx)

Link to comment
Share on other sites

Bon, OK çà doit être une fuite mémoire. Tant pis ! Je vais vivre avec. Cà m'a pris des semaines pour porter PDFBox 1.1.0 sur Android (quand j'ai terminé , la version 1.2.0 été dispo en téléchargement, mais avec des bugs/ralentissements : je suis de loin les issues sur ce projet), je vais pas attendre la version partaite.

Bon, je vais donc limiter les dégats le plus possible.

Merci

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...