Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 5 sur 5
  1. #1
    Invité régulier
    Homme Profil pro Nicolas
    Étudiant
    Inscrit en
    février 2011
    Messages
    8
    Détails du profil
    Informations personnelles :
    Nom : Homme Nicolas

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : février 2011
    Messages : 8
    Points : 5
    Points
    5

    Par défaut Garbage Collector ne libère pas de mémoire

    Bonjour,

    Je suis assez embêté par un petit problème.
    J'essaye de coder un programme qui va rechercher des images (format jpeg, png, ...) sur le disque et qui crée des icones miniatures pour les afficher.

    Ma démarche est la suivante: j'ouvre l'image dans un "BufferedImage", je calcule la futur taille de la miniature puis je met cette miniature dans un ImageIcon.

    Voici la fonction qui effectue cette tâche.

    Code :
    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
     
    public ImageIcon getTiny(int maxWidth, int maxHeight) throws IOException
    {
    	BufferedImage img = null;
    	File fi = new File(_path);
    	if (fi.exists() && fi.isFile() && fi.canRead())
    	{
    		img = ImageIO.read(fi);
    		if (img == null)
    		{
    			throw new IOException("Le fichier \"" + fi.getName() + "\" est illisible");
    		}
    	}
    	else
    	{
    		throw new IOException("Impossible d'ouvrir le fichier \"" + _path +"\"");
    	}
     
    	int wid = img.getWidth();
    	int hei = img.getHeight();
    	float ratio = (float) wid / hei;
    	if (wid >= hei)
    	{
    		wid = maxWidth;
    		hei = (int) (maxWidth / ratio);
    	}
    	else
    	{
    		hei = maxHeight;
    		wid = (int) (maxHeight * ratio);
    	}
    	ImageIcon imIcon = new ImageIcon(img.getScaledInstance(wid, hei,java.awt.Image.SCALE_SMOOTH));
     
    	img = null;
    	System.gc(); // J'essaye de forcer le Garbage collector à nettoyer (mais ça ne marche pas)
     
    	return imIcon;
    }
    Lorsque j'essaye de créer une vingtaine de miniatures (taille maximum 100*100 la miniature) le programme se met à consommer plus de 500 Mo de mémoire.

    J'en déduit donc que le garbage collector ne nettoie pas les bufferedImage (qui contiennent de images assez grandes) malgré mes tentatvies pour forcer la désallocation de mémoire

    Si quelqu'un a une idée je suis preneur

    Merci d'avance

  2. #2
    Membre confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    avril 2007
    Messages
    117
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : avril 2007
    Messages : 117
    Points : 200
    Points
    200

    Par défaut

    Salut,
    Au lieu de faire ton img = null à la fin, essaie un img.flush()

    Mon petit blog sans prétention : http://blog.octera.info/

  3. #3
    Invité régulier
    Homme Profil pro Nicolas
    Étudiant
    Inscrit en
    février 2011
    Messages
    8
    Détails du profil
    Informations personnelles :
    Nom : Homme Nicolas

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : février 2011
    Messages : 8
    Points : 5
    Points
    5

    Par défaut

    Malheureusement ça n'a pas l'air de marcher beaucoup mieux
    Mais merci quand même pour la réponse

    PS: Je ne l'ai pas dit plus haut mais j'utilise java 1.6 (juste au cas où)

  4. #4
    Expert Confirmé Sénior
    Avatar de tchize_
    Homme Profil pro David Delbecq
    Responsable de service informatique
    Inscrit en
    avril 2007
    Messages
    21 772
    Détails du profil
    Informations personnelles :
    Nom : Homme David Delbecq
    Âge : 35
    Localisation : Belgique

    Informations professionnelles :
    Activité : Responsable de service informatique
    Secteur : Service public

    Informations forums :
    Inscription : avril 2007
    Messages : 21 772
    Points : 41 246
    Points
    41 246

    Par défaut

    le System.gc, tu oublie tout de suite ue ça existe, car ça ne fais pas ce que tu veux. Si tu as un out of memory, c'est que le garbage collector a déjà nettoyé et qu'il n'a plsu rien trouvé de récupérable.

    Dans ton cas, tu utilise image.getScaledInstance(). La doc sous entends que cette image réduit ne fait que dessiner l'image principale à une taille plus petite => Elle garde une référence vers l'image principale.

    Crée toi même une nouvelle BufferedImage plus petite et utilise les méthodes de la classe Graphics2D pour dessiner une fois pour toute la grande dans la petite.

    (appel à graphics.drawImage prenant en paramèter un AffineTransform pour la dessiner)
    Tchize (Чиз) faq java, cours java, javadoc. Pensez à et

  5. #5
    Invité régulier
    Homme Profil pro Nicolas
    Étudiant
    Inscrit en
    février 2011
    Messages
    8
    Détails du profil
    Informations personnelles :
    Nom : Homme Nicolas

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : février 2011
    Messages : 8
    Points : 5
    Points
    5

    Par défaut

    Merci, ça consomme déjà beaucoup moins

    Le problème vient bien du fait que

    Code :
    1
    2
     
    ImageIcon imIcon = new ImageIcon(img.getScaledInstance(wid, hei,java.awt.Image.SCALE_SMOOTH));
    garde une référence vers la "grande" image ce qui empêche au garbage collector de faire son boulot

    Si quelqu'un se retrouve confronté un problème similaire, voici comment j'ai implémenté la création de l'image réduite:

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    // La grande image est la variable "img"
    BufferedImage smaller = new BufferedImage(wid, hei,BufferedImage.TYPE_INT_ARGB);
    Graphics2D graph = smaller.createGraphics();
    graph.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
    graph.drawImage(img, 0, 0, wid, hei, null);
    graph.dispose();
    ImageIcon imIcon = new ImageIcon(smaller);
    img = null;

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

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •