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

Android Discussion :

"Out of Memory" incompréhension


Sujet :

Android

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 20
    Points : 11
    Points
    11
    Par défaut "Out of Memory" incompréhension
    Bonjour

    j'ai un problème de mémoire dans mon application que je n'arrive pas à comprendre.

    Lors ce que je navigue au travers des activités il arrive un moment ou elle plante avec :
    08-02 10:55:22.778: E/dalvikvm-heap(990): 1354752-byte external allocation too large for this process.
    08-02 10:55:22.778: E/dalvikvm(990): Out of memory: Heap Size=9415KB, Allocated=5686KB, Bitmap Size=14337KB
    08-02 10:55:22.778: E/GraphicsJNI(990): VM won't let us allocate 1354752 bytes


    et cela sur n'importe quelle activité.

    Les caractéristiques de mon application:
    - Toute les activités sont en noHistory
    - Les interfaces se compose de maximum 10 images pour l'interface
    - Elle se compose d'une activités contenant une liste complexe (qui pourrais être la source de ce problème) ou chaque cellule se compose de 10 images. Le nombre d’élément dans la liste est d'environ 15-20 pour le moment (c'est une boite de réception de message)

    J'ai regarder sur internet et j'y ai vu que c'était lier à un problème d'image. J'ai donc réduit au maximum les images de toute l'interface et l'ai mis un système de cache d'image pour la liste :
    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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    public class ImageCache {
     
    	private HashMap<Integer, Drawable> cacheList = new HashMap<Integer, Drawable>();
    	private static ImageCache uniqueInstance;
    	private Application application;
     
    	private ImageCache() {
     
    	}
    	public static synchronized ImageCache getInstance() {
     
    		if (uniqueInstance == null) {
    			uniqueInstance = new ImageCache();
    		}
    		return uniqueInstance;
    	}
     
    	public void initCache(Application application){
    		this.application = application;
    	}
     
    	public Drawable getDrawable(Integer ressource) {
     
    		if (cacheList.containsKey(ressource)) {
    			return cacheList.get(ressource);
    		} else {
    			Drawable img = application.getResources().getDrawable(ressource);
    			cacheList.put(ressource, img);
    			return img;
    		}
    	}
    }
    a la suite de cela le problème met plus longtemps à se manifester mais persiste tout de même.
    Je suis un peu perdu et je ne comprend pas non plus pourquoi en noHistory les données des Activités ne se vide pas.
    J'ai regarder l'utilisation mémoire sur le DDMS, il reste dans les 70-80% et explose d'un coup (a ce que j'ai comprit)

    Pardon de ne pas vous donner plus d'élément mais si vous avez des hypothèses je vous en dirais plus (comme je vous ai dit je ne sais pas du tout pourquoi sa fait ça)


    MERCI A TOUS !!!!

  2. #2
    Modérateur
    Avatar de Hizin
    Homme Profil pro
    Développeur mobile
    Inscrit en
    Février 2010
    Messages
    2 180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Développeur mobile

    Informations forums :
    Inscription : Février 2010
    Messages : 2 180
    Points : 5 072
    Points
    5 072
    Par défaut
    Attention, ton cache est totalement général.

    Par exemple : tu charges un Drawable UNE fois, elle restera pour toujours référencée et allouée car dans la Map. Le GC ne pourra pas la libérer, même si elle n'est pas utilisée.

    À priori, dans ton pire cas, tu affiches entre 150 et 200 images ("liste complexe, cellule composée de 10 images, 15-20 images"). Vu que tu écris "pour le moment", j'imagine que cela signifie que ça devrait augmenter avec le temps, donc une solution temporaire de rabaissement de mémoire ne fera que reporter le problème, et ne le résoudra pas.

    J'ai dû mettre en place un manager d'image il y a quelque temps aussi, j'avais utilisé un système simple de comptage de référence, couplé avec une Map contenant les Drawable en tant que WeakReference, pour que la Map elle-même ne compte pas au regard du GC.

    Pour voir la mémoire (dans une certaine mesure), tu peux aussi utiliser Debug.getNativeHeapAllocatedSize(). Je m'en sers, en l'encapsulant dans un démon, pour voir l'évolution de la conso mémoire, mais sous ICS+, c'est devenu inutile pour les images (l'impression qu'elles ne sont plus comprises dedans, peut-être depuis HoneyComb, pas testé sous tablette).

    Est-ce que tu utilises aussi du Lazy Loading (chargement à la demande) ?
    Que tu recycles bien tes ImageView pour les présentations en liste ?
    C'est Android, PAS Androïd, ou Androïde didiou !
    Le premier est un OS, le second est la mauvaise orthographe du troisième, un mot français désignant un robot à forme humaine.

    Membre du comité contre la phrase "ça marche PAS" en titre et/ou explication de problème.

    N'oubliez pas de consulter les FAQ Android et les cours et tutoriels Android

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 20
    Points : 11
    Points
    11
    Par défaut
    Pour mon cache je l'ai fait rapidement et comme il ne contient que 10 images je pensais pas que c'était important de les libérer (pour le moment du moins pour voir si cela permettait de résoudre le problème. WeakReference faut que j'essaye oui.

    "tu peux aussi utiliser Debug.getNativeHeapAllocatedSize(). Je m'en sers, en l'encapsulant dans un démon" Qu'est ce qu'un démon ?


    Pour la liste je charge les 10 premiers enregistrements, une fois que j'utilisateur est en bas du scroll j'en charge 10 de plus.
    Non je ne recycles pas mes ImageView, j'ai regarder sur internet et je n'ai pas comprit, j'ai essayer et sa plantait mais si tu as un exemple de code ça pourrait m'aider.

    Je voulais savoir pour le cache tu ne sais pas ou le pourrais trouver une classe toute faite pour gagner du temps ?

  4. #4
    Modérateur
    Avatar de Hizin
    Homme Profil pro
    Développeur mobile
    Inscrit en
    Février 2010
    Messages
    2 180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Développeur mobile

    Informations forums :
    Inscription : Février 2010
    Messages : 2 180
    Points : 5 072
    Points
    5 072
    Par défaut
    Hum ... si tu n'as que 10 images, ce n'est pas la peine de taper dans les WeakReference.

    Citation Envoyé par timlartiste
    "tu peux aussi utiliser Debug.getNativeHeapAllocatedSize(). Je m'en sers, en l'encapsulant dans un démon" Qu'est ce qu'un démon ?
    Un processus tournant en tâche de fond pendant longtemps. Ici, je l'encapsule dans un thread qui me sort la mémoire toute les secondes.
    Code Java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    new Thread() {
     
    	@Override
    	public void run() {
    		while (mustRun) {
    			try {
    				Log.d("run", "" + Debug.getNativeHeapAllocatedSize());
    				sleep(1000);
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		}
    	}
    }.start();

    Citation Envoyé par timlartiste
    Non je ne recycles pas mes ImageView, j'ai regarder sur internet et je n'ai pas comprit, j'ai essayer et sa plantait mais si tu as un exemple de code ça pourrait m'aider.
    Lazy loading, cherche ça. Ce n'est pas très compliqué à comprendre.

    Citation Envoyé par timlartiste
    Je voulais savoir pour le cache tu ne sais pas ou le pourrais trouver une classe toute faite pour gagner du temps ?
    Non. Ca te fera gagner du temps maintenant, ça t'en fera perdre pour la maintenance. Tu ne comprendras pas non plus ce que tu fais.
    C'est Android, PAS Androïd, ou Androïde didiou !
    Le premier est un OS, le second est la mauvaise orthographe du troisième, un mot français désignant un robot à forme humaine.

    Membre du comité contre la phrase "ça marche PAS" en titre et/ou explication de problème.

    N'oubliez pas de consulter les FAQ Android et les cours et tutoriels Android

  5. #5
    Expert éminent

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    Haaaa la joie des memory-leaks....

    Une solution si le OOM se produit toujours au même endroit:
    Le catcher, et au moment ou il arrive, mettre un point d'arrêt pour regarder les objets en mémoire (il y a un outil de Heap dans le DDMS).

    Je subodore une histoire de context conservé en variable globale, et jamais libéré (ce qui est une plaie dans le cas d'une activité, puisque l'activité contient aussi toutes les views, et donc un pointeur sur toutes les images).

    Maintenant pour 10/20 drawable en ressources, ça me semble complètement farfelu ! En effet, Android gère DEJA un cache des drawable (ce qui pose d'ailleurs quelques problèmes quand on veut modifier ceux-ci dynamiquement, il faut explicitement lui dire de faire une version spécifique).

    et 10/20 images dans une interface, c'est loin des 1,3Mo d'allocation que tu demande ! D'ailleurs ils ne sont même pas alloué dans le pool "bitmaps" (qui a encore 14 Mo de libre !)... Ca fait quand même une image de 580x580 environ, un peu grand pour une interface ?

    Bref, il va nous falloir plus de détails....

    Au passage, outre les WeakReference<> il y a un truc bien pratique: les SoftReference<> ce sont des WeakReference qui ne sont libéré que si un OOM est sur le point de survenir....
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  6. #6
    Modérateur
    Avatar de Hizin
    Homme Profil pro
    Développeur mobile
    Inscrit en
    Février 2010
    Messages
    2 180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Développeur mobile

    Informations forums :
    Inscription : Février 2010
    Messages : 2 180
    Points : 5 072
    Points
    5 072
    Par défaut
    Citation Envoyé par Nicroman
    Au passage, outre les WeakReference<> il y a un truc bien pratique: les SoftReference<> ce sont des WeakReference qui ne sont libéré que si un OOM est sur le point de survenir....
    Ah, tiens, merci pour ce point, je n'avais pas été jusque là (avec une meilleure gestion des images, il s'est révélé que mon cache perso était inutile ...).
    C'est Android, PAS Androïd, ou Androïde didiou !
    Le premier est un OS, le second est la mauvaise orthographe du troisième, un mot français désignant un robot à forme humaine.

    Membre du comité contre la phrase "ça marche PAS" en titre et/ou explication de problème.

    N'oubliez pas de consulter les FAQ Android et les cours et tutoriels Android

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 20
    Points : 11
    Points
    11
    Par défaut
    nicroman, le crach ne se produit pas au même endroit mais se produit à l'ouverture d'une activité et selon mes tests surtout sur "setContentView()".

    Pour le try catch j'ai essayer et cela ne fonctionne pas, l'application se ferme complètement et donc ne passe pas par le catch.

    nicroman je suis d'accord avec toi c'est surprenant que mon application que n'ai pas lourd plante à cause des images et j'aime bien ton hypothèse de context.

    Je vous donne plus de détail mais je ne peux pas non plus en dire trop (à cause du client).

    J'ai remarqué que l'application plante quand il y a au moins un passage dans l'activités avec la listview donc je vais me concentrer la dessus:

    Pour commencer l'application se connecte à un service web au travers d'une API qui permet des appels asynchrone. pour envoyer une requête je fais appel a un singleton (qui à une référence vers "application") et l'appel la méthode correspondante à la requête à faire en passant en paramètre un Handler(dans l'activité elle même je déclare cette Handler comme class local
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    private class LocalHandler extends Handler
    ). L'API place ce handler dans une Map, réalise la requete, retrouve le Handler passé en paramètre, lui envoi un message puis le supprime de la Map.

    La listview, pour la remplir j'utilise un ArrayAdapter<Object>. A chaque fois que je dois re-remplir la list de fait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    listView.setAdapter(new CAdapter(...
    . Les cellules se compose de 10 images inséré pendant le de l'adapter (il y a plusieurs cas possible et en fonction de ces cas les images ne sont pas les même). A chaque se produisent 7 fois
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ((ImageView) v.findViewById(R.id.aaaaaaaa)).setImageDrawable()
    Chaque cellules se compose de 8 évènements OnClick sur les images.

    Besoin de plus ?

    En tout cas merci beaucoup à tout les deux pour votre aide.

  8. #8
    Expert éminent

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    Un peu plus de code sera bienvenue oui... surtout l'Adapter si le probleme est dans la ListView....

    Sinon, une option, est de lancer l'activité avec la ListView
    Sortir de l'activité (avant l'OOM)
    Et de tout de suite regarder dans la Heap si l'activité est toujours là (éventuellement forcer un petit GC), ou si des objets sont toujours là....

    On pourrait avoir la stack-trace de l'OOM ?
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 20
    Points : 11
    Points
    11
    Par défaut
    Bonjour

    Pardon pour la période de silence j'avais beaucoup à faire.

    J'ai réussi à régler le problème de dépassement de mémoire.

    Pour commencer voila deux ressources qui m'ont permit de trouver les réponses:
    http://www.mindfiresolutions.com/Mem...ation-2040.php
    http://ttlnews.blogspot.fr/2010/01/a...n-android.html

    Mon problème de mémoire pouvait être dû à deux éléments possible :
    - d'abord, le fait que l'application soit en mode debug (dans le manifest, dans le nœud application 'android:debuggable="true"'). Dans les ressources ci-dessus il est dit que dans ce mode là, les objets ne sont pas supprimé pas le garbage collector ce qui peut entraîner des problèmes de dépassement de mémoire. Ainsi je conseil à ceux qui ont des dépassements de vérifier si le problème persiste dans le cas de "debuggable" est à "false".

    - ensuite comme disait "nicroman" le problème était la conservation du context pouvant empêcher les activity de se fermer totalement. En effet j'utilisais pas mal d'objet ayant besoin du context ainsi il était tout a fait possible que l'un d'eux provoque des erreurs de dépassement de mémoire à force d'ouvrir et de fermer les activity de l'application. Ainsi pour régler le problème, j'ai surcharger la méthode "finish()" des activity et j'ai nettoyer les variables en leur mettant les variables de context à null.


    Voila merci à vous pour votre aide.
    PS : je ne clôture pas la discussion tout de suite pour vous permettre de réagir sur ce dernier message.

  10. #10
    Expert éminent

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    Par contre passer en "Résolu" ne clôt pas la discussion
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. out of memory incompréhensible.
    Par Virgile le chat dans le forum Langage
    Réponses: 3
    Dernier message: 24/05/2007, 23h35
  2. [C++] [gcc] out of memory
    Par fxp17 dans le forum GCC
    Réponses: 5
    Dernier message: 06/01/2006, 10h29
  3. [pb mémoire] out of memory d'eclipse
    Par Casp dans le forum Eclipse Java
    Réponses: 2
    Dernier message: 12/05/2005, 16h39
  4. Out of memory
    Par shurato dans le forum ANT
    Réponses: 1
    Dernier message: 10/11/2004, 16h19
  5. [JBuilder 8] Out of memory problem ...
    Par keros dans le forum JBuilder
    Réponses: 2
    Dernier message: 08/09/2003, 19h03

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