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 :

Problème ressource GC_FOR_MALLOC freed objects


Sujet :

Android

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    177
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 177
    Points : 73
    Points
    73
    Par défaut Problème ressource GC_FOR_MALLOC freed objects
    Bonjour

    Je fais du streaming avec des bitmap dans mon application. Je croyais que cela fonctionnait mais au bout de 3 min, il me met :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    android D/dalvikvm(): GC_FOR_MALLOC freed objects
    J'ai cette ligne qui s'affiche à toute vitesse sans arreter me bloquant l'application. Le souci est que je n'arrive pas a savoir ou est le probleme car il me met aucune erreur ds mes log. Je ne sais pas quoi car j'ai l'impression de bien vider mes btimap.recycle()

    Connaisez vous ce genre de probleme ?

    Merci de votre aide

  2. #2
    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
    android D/dalvikvm(): GC_FOR_MALLOC freed objects

    est normalement appelée régulièrement...
    En général cette ligne ne vient pas seule, mais avec un peu de logs autours...
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    177
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 177
    Points : 73
    Points
    73
    Par défaut
    Et non j'ai aucun log me donnant une infos sur l'erreur entre les lignes .
    Je pense que l'erreur vient de ma méthode connect(). J'ai une boucle infinie avec un while ou se trouve justement ma méthode connect(). J'utilise un mutlipartentity pr mes connexions ds ma méthode connect().

    Cela veut dire que j'instancie à chaque boucle un multipartentitiy. J'ai un doute sur le faite qu'il faut l'appeler qu'une fois et non a chaque appel le mmutlipartentity ??

    Pouvez me dire votre par rapport a cela

    Merci

  4. #4
    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
    Mode divination enclenché ....
    Non je vois rien désolé....

    Un petit bout de code peut-être ?
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  5. #5
    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
    Ca s'appelle soit dans les cas de boucle infini, soit dans les phases de créations d'objets en gros volume d'expérience.

    Sinon, comme Nicroman : la divination, c'est pas encore au point
    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

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    177
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 177
    Points : 73
    Points
    73
    Par défaut
    Oui désolé pour le mode divination

    Effectivement sans bout de code ca sera dur pour m'aider. Alors j'ai essayé de mieux debuguer mon probleme ms tjs pas de solution.

    Voici ma boucle infinie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    while(!done && error==false){
     canvas = surfaceHolder.lockCanvas();
     canvas.drawBitmap(lireMJPG(),0,0,null);
     lireMJPG().recycle();
     surfaceHolder.unlockCanvasAndPost(canvas);
    }
    lireMJPG() :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    /**
    * Prétraite les flux MJPG pour enlever l'encapsulation MJPG
    * @throws IOException
    */
    public Bitmap lireMJPG() {
    	lireLigne(2, dis); // jete les 2 premières lignes
    	ligne3 = lireLigne(dis);
    	contentLen = Integer.parseInt((ligne3.split(":")[1].trim()));
    	lireLigne(1, dis);
    	bit = lireJPG(contentLen);
    	readLine(1, dis); // jete la dernière ligne
    	return bit;
    }
    Suite...
    /**
    * Boucle sur dataInputStream
    * @param n
    * @param dis
    */
    public void lireLigne(int n, DataInputStream dis) {
    for (int i = 0; i < n; i++) {
    lireLigne(dis);
    }
    }

    Je pense (mais pas sur ) que le probleme vient de cette méthode qui est appelé plusieurs fois pour une image en plus présente dans ma boucle infinie...
    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
     
    /**
     * Sépare et lecture d'une ligne
     * @param dis
     * @return
     */
    public String lireLigne(DataInputStream dis) {
    	result = "";
    	try {
    		end = false;
    		String lineEnd = "\n"; // suppose que la fin de la ligne est marqué avec un saut de ligne
    		lineEndBytes = lineEnd.getBytes();
    		byteBuf = new byte[lineEndBytes.length];
    		while (!end && !error) {
    			dis.read(byteBuf, 0, lineEndBytes.length);
    			t = new String(byteBuf);
    			result += t;
    			if (t.equals(lineEnd)) {
    				end = true;
    			}
    		}
    	} catch (Exception e) {
    		try {
    			dis.close();
    		} catch (IOException e1) {
    			e1.printStackTrace();
    		}
    		error = true;
    		e.printStackTrace();
    	}
    	return result;	
    }
    Je sais pas quoi faire, j'ai peur de devoir concevoir mon code autrement ms c'eszt vraiment bizarre car cela marche parfaitement pendant 3 min et d'un coup, il me vide en GC_FOR_MALLOC a tte vitesse et bloque l'applie....

    Une idée ?

  7. #7
    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
    Alors je ne suis pas sur pour le malloc... mais je vais juste donner deux ou trois recommandations de programmation....

    "Bitmap" est une ressource qui demande pas mal de mémoire... readMJPGStream() est un "allocateur de ressource"...
    On va donc "encapsuler" le code d'utilisation:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    while(!done{
     Bitmap bitmap = readMJPGStream();
     try {
         canvas = surfaceHolder.lockCanvas();
         canvas.drawBitmap(bitmap,0,0,null);
         surfaceHolder.unlockCanvasAndPost(canvas);
      } finally {
         if (bitmap != null) bitmap.recycle();
      }
    }
    Ensuite les gens ont toujours tendance à trop catcher les exceptions de partout, et du coup, ne plus "voir" ces exceptions (cas d'erreur) par la suite... Par exemple, dans le code de readMJPGStream, que se passe-t-il si ligne3=readLine(dis) foire (exception, 'error' est à vrai) ? => bim on passe à la ligne suivante, ligne3.split() avec ligne3 à null et donc une NPE de base.



    Donc, la fonction qui pose soucis c'est readLine....
    D'abord readLine prend en paramètre un stream (ressource), ce n'est donc certainement pas à readLine de fermer le stream !!!
    Mais surtout... pourquoi catcher l'exception ? (et la faire disparaître dans les méandres du System.err )

    Déjà, je pense que si tu vires tous les try/catch (et ne conserve que les try/finally pour la gestion des ressources) il y aura un poil plus d'information.
    Eventuellement fait un truc genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    } catch (IOException ex) {
        Log.w("MY_TAG","Error while processing stream...",ex);
        throw ex;
    }
    L'autre interêt de ne pas catcher les exceptions, est de ne pas avoir à gérer de "boolean error" !
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    177
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 177
    Points : 73
    Points
    73
    Par défaut
    Ok interessant tt ca, il est clair il y a des soucis d'algo a régler

    J'ai fait les changements de cette façon et j'obtiens une fatal exception :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Canvas: trying to use a recycled bitmap android.graphics.Bitmap@44fa0eb8
    Voici ce que j'ai modifié :
    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
     
    while(!done && error==false){
    	try{
    		canvas = surfaceHolder.lockCanvas();
    		canvas.drawBitmap(readMJPGStream(),0,0,null);
    		surfaceHolder.unlockCanvasAndPost(canvas);
    	}
            finally{
    		 if (readMJPGStream() != null) {
    		     Log.w(LOG_TAG_EYE_SEE_U, "Essaye readMJPGStream() recycle()");
    		     readMJPGStream().recycle();
    		     Log.w(LOG_TAG_EYE_SEE_U, "readMJPGStream() recycle()");
                     }
    	         else Log.w(LOG_TAG_EYE_SEE_U, "prob readMJPGStream() recycle()))");
    	}
    }
    readMJPGStream():
    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
     
    public Bitmap readMJPGStream() {
    		readLine(2, dis); // jete les 2 premières lignes
    		ligne3 = readLine(dis);;
    		contentLen = Integer.parseInt((ligne3.split(":")[1].trim()));
    		readLine(1, dis);
    		bit = readJPG(contentLen);
    		try{
    		readLine(1, dis); // jete la dernière ligne
    		}finally{
    			if (bit != null){
    				Log.w(LOG_TAG_EYE_SEE_U, "Essaye bit recycle()");
    				bit.recycle();
    				Log.w(LOG_TAG_EYE_SEE_U, "Ok bit recycle()");
    			}
    			else Log.w(LOG_TAG_EYE_SEE_U, "prob bit recycle");
    		}
    		return bit;
    	}
    readLine(DataInputStream dis) :
    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
     
    /**
             * Sépare et lecture d'une ligne
             * @param dis
             * @return
             */
    	public String readLine(DataInputStream dis) {
    		result = "";
    		try {
    			end = false;
    			String lineEnd = "\n"; // suppose que la fin de la ligne est marqué avec un saut de ligne
    			lineEndBytes = lineEnd.getBytes();
    			byteBuf = new byte[lineEndBytes.length];
    			while (!end && !error) {
    				dis.read(byteBuf, 0, lineEndBytes.length);
    				t = new String(byteBuf);
    				result += t;
    				if (t.equals(lineEnd)) {
    					end = true;
    				}
    			}
    		} catch (IOException ex) {
    			Log.w("MY_TAG","Error while processing stream...",ex);
    			try {
    				throw ex;
    			} catch (IOException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    		return result;	
    	}
    Je continue a chercher ds ce sens mais est ce que ca ne voudrait pas dire qu'il n'arrive donc pas a chaque à vider mes bitmap ???
    Pourtant ceux du haut ds la boucle while, je pratiquement sur qu'a chaque image il me vidait ma bitmap. Le truc est que j'utilise plusieurs bitmap, il n'arrive peut etre pas a tt vider. Selon toi ?

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    177
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 177
    Points : 73
    Points
    73
    Par défaut
    Je fais un dernier petit up, j'ai bo chercher je ne trouve de solution... Si quelqu'un a une isnpiration je suiis preneur

  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
    Bon... alors il y a une excellente vidéo sur le GC dans Dalvik qui explique deux/trois trucs....

    Il y a plusieurs types de GC:
    GC_CONCURRENT: qui est appelé de manière "concurrente" (avec néanmoins deux tous petits freeze) dès que la heap commence à saturer (autour de 70%)
    GC_FOR_ALLOC: qui est appelé quand l'application n'arrive plus à allouer un objet Java.
    GC_FOR_MALLOC: qui est appelé quand l'application n'arrive plus à allouer de la mémoire "externe" (le byte[] des bitmaps par exemple).
    ....

    Je te conseille un truc....
    Installe MAT pour Eclipse
    Quand le probleme arrive, fait un memory dump et tu verras vite qui "occupe" la mémoire.

    Ensuite dans ton code, tu es conscient que tu utilises DEUX FOIS readMjpgStream(), (donc a priori tu récupère deux images) à chaque itération !
    Dans ton nouveau code tu le fait même 3 FOIS !!!!!
    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
    while(!done && error==false){
    	try{
    		canvas = surfaceHolder.lockCanvas();
    		canvas.drawBitmap(readMJPGStream(),0,0,null);
    		surfaceHolder.unlockCanvasAndPost(canvas);
    	}
            finally{
    		 if (readMJPGStream() != null) {
    		     Log.w(LOG_TAG_EYE_SEE_U, "Essaye readMJPGStream() recycle()");
    		     readMJPGStream().recycle();
    		     Log.w(LOG_TAG_EYE_SEE_U, "readMJPGStream() recycle()");
                     }
    	         else Log.w(LOG_TAG_EYE_SEE_U, "prob readMJPGStream() recycle()))");
    	}
    }
    Une boucle va donc:
    Récupérer une bitmap #1, et la dessiner
    Récupérer une bitmap #2, et si elle n'est pas nulle, Récupérer une bitmap #3 et la libérer !!!
    Donc a chaque itération, on aura 2 bitmaps non recyclées... qui devront être récupérée par le GC (et avec le finalizer, il faut compter 2/3 itérations avant qu'une bitmap ne soit complètement libérée).

    Il faut STOCKER la bitmap #1 (et pas appeler la fonction sans arrêt) (regarde l'exemple de mon code !)


    A CHAQUE appel de readMjpgStream, doit correspondre un bitmap.recycle() à priori !

    Et puis ca:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    } catch (IOException ex) {
    			Log.w("MY_TAG","Error while processing stream...",ex);
    			try {
    				throw ex;
    			} catch (IOException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    Ca ne sert à rien !!!
    Autant mettre e.printStackTrace() directement.... Je le fais en langage "normal":
    En cas d'exception IO ex:
    Fait un log (parfait)
    Essaye de:
    ... lancerl'exception (IO)
    en cas exception IO e (donc toujours vrai avec e == ex)
    ... e.printStackTrace()

    Vires entierement les try/catch boudiou !!!
    Ils ne servent à rien dans cette fonction !

    Et pour finir, la cerise:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    		try{
    		readLine(1, dis); // jete la dernière ligne
    		}finally{
    			if (bit != null){
    				Log.w(LOG_TAG_EYE_SEE_U, "Essaye bit recycle()");
    				bit.recycle();
    				Log.w(LOG_TAG_EYE_SEE_U, "Ok bit recycle()");
    			}
    			else Log.w(LOG_TAG_EYE_SEE_U, "prob bit recycle");
    		}
    Donc dans tous les cas, si on arrive à lire une bitmap, on la jette (recycle) !!!

    Non, c'est en CAS D'EXCEPTION qu'il faut la jeter !!!

    Logique d'un utilisation de ressource:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    RESOURCE r = null;
    try {
       r = acquisitionResource();   // chez toi readMjpgStream();
       ....
    } finally {
       if (r != null)
          liberationResource(r);  // chez toi bitmap.recycle();
    }

    Logique de l'acquisition de ressource (readMjpgStream):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    RESOURCE ret = null;
    try {
        ....
        ret = ...; // création ressource
        ....
    } catch (Exception ex) {   // IOException dans ton cas
        if (ret != null)
           liberationResource(ret); // bitmap.recycle();
        ret = null;
        throw ex; // on redispatch l'exception
    }
    return ret;
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  11. #11
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    177
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 177
    Points : 73
    Points
    73
    Par défaut
    Merci pour ton aide, ca permet d'essayer d'avancer ms j'ai tjs l'erreur, je pense qd meme que mon flux va plus vite en utisant une et une bitmap . J'étais tromper un copiant mon ancien code pour l'utilisation de mes bitmaps.

    Donc avec tes changements cela donne ceci ms sans succé :

    Mon thread ou se trouve ma boucle infinie :
    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
     
    public void run(){
    	SurfaceHolder surfaceHolder = holder;
    	Canvas canvas = null;
    	while(!done && error==false){
    		try{
    			canvas = surfaceHolder.lockCanvas();
    			canvas.drawBitmap(readMJPGStream(),0,0,null);
    			surfaceHolder.unlockCanvasAndPost(canvas);
    		}finally{
    			if (bitmapScaled.isRecycled()==false) {
    				bitmapScaled.recycle();
    			}else Log.e(LOG_TAG_EYE_SEE_U, "prob readMJPGStream() or bitmapScaled recycle()))");
    		}
    	}
    }
    Méthode Bitmap readMJPGStream() :
    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
     
    public Bitmap readMJPGStream() {
    	String ligne3 = "";
    	int contentLen = 0;
    	try{
    		readLine(2, dis); // jete les 2 premières lignes
    		ligne3 = readLine(dis);
    		contentLen = Integer.parseInt((ligne3.split(":")[1].trim()));
    		readLine(1, dis);
    		bitmapScaled = readJPG(contentLen);
    		readLine(1, dis); // jete la dernière ligne
    	}catch (Exception e) {
    		if (bitmapScaled.isRecycled()==false) {
    			bitmapScaled.recycle();
    		}
    		if(!ligne3.equals("")||!(contentLen==0)){
    			ligne3="";
    			contentLen=0;
    		}else{
    			Log.e(LOG_TAG_EYE_SEE_U, "Valeur de ligne3 ou contentLen pas null");
    		}
    		try {
    			throw e;
    		} catch (Exception e1) {
    			Log.e(LOG_TAG_EYE_SEE_U, "bitmapScaled recycle() ds 2eme methode");
    			e1.printStackTrace();
    		}
    	}
    	return bitmapScaled;
    }
    Méthode String readLine(DataInputStream dis) :
    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
     
    public String readLine(DataInputStream dis) {
    	result = "";
    	try {
    		end = false;
    		String lineEnd = "\n"; // suppose que la fin de la ligne est marqué avec un saut de ligne
    		lineEndBytes = lineEnd.getBytes();
    		byteBuf = new byte[lineEndBytes.length];
    		while (!end && !error) {
    			dis.read(byteBuf, 0, lineEndBytes.length);
    			t = new String(byteBuf);
    			result += t;
    			if (t.equals(lineEnd)) {
    				end = true;
    			}
    		}
    	} 
    	catch (IOException e1) {
    		Log.e(LOG_TAG_EYE_SEE_U, "result readline prob ");
    		error = true;
    		e1.printStackTrace();
    	}
    	return result;	
    }
    methode Bitmap readJPG(init i) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    public Bitmap readJPG(int i){
    	try {
    		byte[] f = new byte[i];
    		dis.readFully(f, 0, i);
    		bitmapScaled = BitmapFactory.decodeStream(new ByteArrayInputStream(f));
    		f=null;
    	} catch (IOException e) {
    		Log.w("MY_TAG","PROBLEME DS readJPG");
    		e.printStackTrace();
    	}
    	return bitmapScaled;
    }
    J'ai aussi installé MAT, ca a l'air tres puissant comme outil mais pas facile a installer. Dans l'histogramme de mon fichier HPROF, la classe qui créé le plus d'objet est "java.lang.String" 14838 (Objects) de 356 000 (shallow heap) retenant 927 000 de données (retained heap). C'est la plus grosse montée.
    Si je fais un click droit sur cette valeur/list objects/with incoming references = difficile d'exploiter les résultats. Débutant avec ce debug je vois rien de particulier.
    Je me demande si cette classe ne correspond pas à ma méthode readline(datainputstream dis) car elle retourne un string. Vs allez me dire rien de bien nouveau

    Le nom de la 2 eme classe ayant la plus grosse montée (puis les autre sont bien inférieure) est "char[] avec 13173 objects créées de 735 000 (shallow heap) retenant 735 000 de données (retained heap).
    Lorsque je fais cette fois ci click droit sur cette valeur/list objects/with incoming references = je retrouve 2 lignes :
    [code]
    char[19655] @... \uu000\u000\u000\u000\u000\u000\u000\u000\u000\.. avec 40Ko. Dans les 2 lignes il mets en évidence "la référence" de mon thread qui englobe le tout (ma boucle infinie, readMJPGStream, readJPG(int i)...) . Exactement ces cette ligne a cdhaque fois qui se repete et qui est bien au dessus des autres :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    <Java Local>, this$0 mon.package.maClasse.classeInterneThread @ 0x44ef0970 Thread-15 Thread
    /**classeInterneThread = la ou se trouve tte mes methodes boucle infinie etc...*/
    A votre avis ? J'ai exporter certaines feuilles de mon debug en PJ
    Fichiers attachés Fichiers attachés

  12. #12
    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
    Tu es conscient que ton premier snippet fait ceci :
    Code Java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public void run(){
    	SurfaceHolder surfaceHolder = holder;
    	Canvas canvas = null;
    	while(!done && error==false){
    		canvas = surfaceHolder.lockCanvas();
    		canvas.drawBitmap(readMJPGStream(),0,0,null);
    		surfaceHolder.unlockCanvasAndPost(canvas);
    		if (bitmapScaled.isRecycled()==false) {
    			bitmapScaled.recycle();
    		}else Log.e(LOG_TAG_EYE_SEE_U, "prob readMJPGStream() or bitmapScaled recycle()))");
    	}
    }
    ?
    Pas de catch, donc finally toujours effectué une fois le try fini, pas d'exception possible (puisque pas de catch), donc aucune opération non-effectuée.

    Second snippet :
    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
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
     
    public Bitmap readMJPGStream() {
    	String ligne3 = "";
    	int contentLen = 0;
    	try{
    		readLine(2, dis); // jete les 2 premières lignes
    		ligne3 = readLine(dis);
    		contentLen = Integer.parseInt((ligne3.split(":")[1].trim()));
    		readLine(1, dis);
    		bitmapScaled = readJPG(contentLen);
    		readLine(1, dis); // jete la dernière ligne
    	}catch (Exception e) {
    		if (bitmapScaled.isRecycled()==false) {
    			bitmapScaled.recycle();
    		}
    		if(!ligne3.equals("")||!(contentLen==0)){
    			ligne3="";
    			contentLen=0;
    		}else{
    			Log.e(LOG_TAG_EYE_SEE_U, "Valeur de ligne3 ou contentLen pas null");
    		}
     
    		Log.e(LOG_TAG_EYE_SEE_U, "bitmapScaled recycle() ds 2eme methode");
    		e.printStackTrace();
     
    	}
    	return bitmapScaled;
    }

    Troisième snippet :
    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
    15
    16
    17
    18
    19
    20
    21
    22
    public String readLine(DataInputStream dis) {
    	StringBuilder result = new StringBuilder();
    	try {
    		end = false;
    		String lineEnd = "\n"; // suppose que la fin de la ligne est marqué avec un saut de ligne
    		lineEndBytes = lineEnd.getBytes();
    		byteBuf = new byte[lineEndBytes.length];
    		while (!end) {
    			dis.read(byteBuf, 0, lineEndBytes.length);
    			t = new String(byteBuf);
    			result.append(t);
    			if (t.equals(lineEnd)) {
    				end = true;
    			}
    		}
    	} 
    	catch (IOException e1) {
    		Log.e(LOG_TAG_EYE_SEE_U, "result readline prob ");
    		e1.printStackTrace();
    	}
    	return result.toString();	
    }

    Quatrième snippet :
    Code Java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public Bitmap readJPG(int i){
    	Bitmap bitmapScaled = null;
    	try {
    		byte[] f = new byte[i];
    		dis.readFully(f, 0, i);
    		bitmapScaled = BitmapFactory.decodeStream(new ByteArrayInputStream(f));
    		f=null;
    	} catch (IOException e) {
    		Log.w("MY_TAG","PROBLEME DS readJPG");
    		e.printStackTrace();
    	}
    	return bitmapScaled;
    }



    Je pense que le code de ta boucle infinie (et celui qui l'englobe et l'appel) serait intéressant.
    Si tu fais des concaténations de chaîne dans une boucle, utilises plutôt une StringBuilder plutôt qu'une String (tu as un exemple d'utilisation dans un des snippets), et regardes la doc au besoin.
    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

  13. #13
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    177
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 177
    Points : 73
    Points
    73
    Par défaut
    Désolé correction premier snippet (je suis allé trop vite) :
    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
     
    public void run(){
    	SurfaceHolder surfaceHolder = holder;
    	//Répéte la boucle de dessin jusqu'a ce que le thread soit stoppé
    	Canvas canvas = null;
    	while(!done && error==false){
    		try{
    			canvas = surfaceHolder.lockCanvas();
    			canvas.drawBitmap(readMJPGStream(),0,0,null);
    			surfaceHolder.unlockCanvasAndPost(canvas);
    		}finally{
    			if (bitmapScaled.isRecycled()==false) {
    				bitmapScaled.recycle();
    			}
    			else Log.e(LOG_TAG_EYE_SEE_U, "prob readMJPGStream() or bitmapScaled recycle()))");
    		}
    	}
    }
    Je n'ai pas trop compris le sens de ta phrase :
    "Je pense que le code de ta boucle infinie (et celui qui l'englobe et l'appel) serait intéressant."
    ??

    Je vais me pencher sur les "StringBuilder", voir si ca me permettre d'ameliorer les choses.

    Merci

  14. #14
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    177
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 177
    Points : 73
    Points
    73
    Par défaut
    J'ai essayé de corriger ma classe avec un stringbuilder. Ca ameliore un peu le temps de chargemement mais ca bloque tjs.

    Est ce que j'utilise correctement le stringbuilder ??? selon vous :
    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
     
    public String readLine(DataInputStream dis) {
    	result = "";	
    		try {
    			end = false;
    			String lineEnd = "\n"; // suppose que la fin de la ligne est marqué avec un saut de ligne
    			lineEndBytes = lineEnd.getBytes();
    			byteBuf = new byte[lineEndBytes.length];
    			int tLenght=1;
    			int resultLenght=0;
    			while (!end && !error) {
    				dis.read(byteBuf, 0, lineEndBytes.length);
    				t=new String(byteBuf);
    				tLenght = t.codePointCount(0, t.length());
    				resultLenght = result.codePointCount(0, result.length()); //defini la taille exact cela ameliore le stringbuilder
    				sBuilder = new StringBuilder(tLenght+resultLenght);
    				sBuilder.append(result).append(t);
    				result = sBuilder.toString();
    				if (t.equals(lineEnd)) {
    					end = true;
    				}
    			}
    		} 
    		catch (IOException e1) {
    			Log.e(LOG_TAG_EYE_SEE_U, "result readline "+compte+" = "+result);
    			error = true;
    			e1.printStackTrace();
    		}
    		return result;	
    	}
    Mais je suis pas sur que le souci b=veint de là... Quelle galereeeeeeee

    Merci

  15. #15
    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
    Je pense que tu mélange trop de choses, en essayant de grouper le code non pas par classe, mais par style de fonction (bref pas de l'OO mais du fonctionnel de base).

    D'un coté on a l'interface.... Elle a grosso modo un "MjpegStream"... et le lit pour mettre à jour son canvas.
    Ton code devient alors (on va dire que MyActivity est la classe englobante du thread, et qu'il contient un SurfaceHolder: holder et un MjpegStream: mjpgStream)
    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
     
    public void run() {
    	//Répéte la boucle de dessin jusqu'a ce que le stream soit fini, ou le thread stoppé
    	while (!done) { 
                    Bitmap bitmap = null;
    		try {
                           // resource acquisition
                           bitmap = MyActivity.this.mjpgStream.readBitmap();
                           // resource usage
                           if (bitmap != null) {
                               Canvas canvas = MyActivity.this.holder.lockCanvas();
    		           canvas.drawBitmap(bitmap,0,0,null);
    		           MyActivity.this.holder.unlockCanvasAndPost(canvas);
                           } else {
                               // end of file !
                               done = true;
                           }
    		}finally {
                           // resource release (toujours executé même en cas d'exception)
                           if (bitmap != null && !bitmap.isRecycled())
                                bitmap.recycle();
                           bitmap = null; // juste au cas ou le GC passerait pendant readBitmap(), l'objet bitmap précédent n'a plus de reference et pourra donc être collecté !
    		}
    	}
    }
    A noter les "MyActivity.this." pour spécifier que l'objet est un membre de la classe MyActivity ! Il n'y a que deux références externes: mjpegStream (le stream de lecture) et holder (le SurfaceHolder d'écriture).
    Le "done" est mis à vrai quand on recoit une bitmap nulle... (marque de "fin" de stream).

    Ensuite il y a une classe de MjpegStream:
    Commençons par readJPG(int) ... elle doit obligatoire passer l'IOException à l'appelant...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public Bitmap readJPG(int i) throws IOException
    {
        byte[] f = new byte[i];
        dis.readFully(f, 0, i);
        // Attention ... a partir de là on va pouvoir avec une erreur !    
        return BitmapFactory.decodeStream(new ByteArrayInputStream(f));
    }
    A noter qu'il n'y a pas besoin de "releaser" la ressource en cas d'exception vu que c'est la dernière chose effectuée avant le return !

    La fonction qui me pose le plus de problème c'est readLine(DataInputStream)
    Je ne sais pas du tout ce que tu y fais... tu pars d'une chaine constante "\n" tu l'assigne à une string (en fait la String lineEnd *sera* la chaine constante), puis tu demande ses bytes (en UTF-8 donc), byteBuf est donc un tableau de bytes de longueur 1 la plupart du temps (mais pas obligatoirement), tu convertis ce tableau en String (ça risque donc de ne pas marcher pour certains caractères, d'autant que DataInputStream n'utilise pas UTF-8, mais FSS_UTF...) et tu rajoute la String à un résultat...
    C'est lent, et surtout... complètement faut.... il faut utiliser readChar()
    Donc je pense que la classe MJpegStream doit contenir un "buffer" et devient donc:
    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
     
    class MJpegStream
    {
         DataInputStream base;
         boolean eof;
     
         public MJpegStream (DataInputStream dis)
         {
              this.base = is;
              this.eof = false;
         }
     
         public void close()
         {
              this.base.close();
         }
     
         public boolean isEOF()
         {
              return this.eof;
         }
     
         String readLine() throws IOException
         {
              if (this.eof) return null;
              StringBuilder builder = new StringBuilder();
              boolean eol = false;          
              while (!eol) {
                 try {
                     char c =this.base.readChar();
                     if (c == '\n')
                         eol = true;
                     else
                         builder.append(c);
                 } catch (EOFException eof) {
                    this.eof = true;
                    eol = true;
                 }
              }
              return builder.toString();
         }
     
         void skipLines(int nlines) throws IOException
         {
             while (nlines--) readLine(); // peut être optimisé je pense
         }
     
         // toujours utiliser des parametres qui veulent dire quelque chose !
         Bitmap readJPG(int length) throws IOException
         {
            if (this.eof) return null;
            if (length == 0) return null;
     
            try {
                byte[] buf = new byte[length];
                dis.readFully(f);
                // pas la peine de passer par un bytearraystream !
                return BitmapFactory.decodeByteArray(buf,0,length);
            } catch (EOFException eof) {
                this.eof = true;
                return null;
            }
         }
     
         public Bitmap readBitmap() {
            if (this.eof) return null;
     
            Bitmap ret = null;
    	String ligne3;
    	int contentLen = 0;
    	try{
    		skipLines(2); // jete les 2 premières lignes
    		ligne3 = readLine();
    		contentLen = Integer.parseInt((ligne3.split(":")[1].trim()));
    		skipLines(1);
    		ret = readJPG(contentLen);
    		skipLines(1); // jete la dernière ligne
    	} catch (IOException e) {
                    // si on a une exception et qu'une image a été allouée, on la détruit !
    		if (ret != null)
                        ret.recycle();
                    ret = null;
                    throw e;
            }
    	return ret;
    }
    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. Problème Ressource demandée indisponible
    Par reeda dans le forum JSF
    Réponses: 12
    Dernier message: 09/10/2008, 14h05
  2. Problème ressource non disponible
    Par tomy29 dans le forum JSF
    Réponses: 2
    Dernier message: 20/07/2008, 16h00
  3. Probléme ressource avec Tutorial
    Par davlefou dans le forum Ogre
    Réponses: 11
    Dernier message: 25/01/2008, 22h09
  4. [HTML/Object] Problème superposition calques (tag <object
    Par busmik dans le forum Balisage (X)HTML et validation W3C
    Réponses: 3
    Dernier message: 28/11/2005, 11h02

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