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

Langage Java Discussion :

Gros problème de mémoire


Sujet :

Langage Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Février 2010
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 17
    Par défaut Gros problème de mémoire
    Bonjour à tous,

    Mon application parse un gros fichiers d'environ 150mo, le problème est que je me retrouve avec 380mo d'utilisation mémoire.

    Mon problème est que je n'arrive pas à vider la mémoire ( même en forçant le garbage collector )

    Voici le code incriminé :
    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
     private static void init() {
    		System.out.println(">>>> Parsing >>>");
    		File f = null;
    		FileInputStream fis = null;
    		byte[] ba = null;
     
    		try {
    			// open a file and read the content into a byte array
    			f = new File(ConfigManager.PATH_TO_HIERARCHY + current_filename);
    			fis = new FileInputStream(f);
    			ba = new byte[(int) f.length()];
    			fis.read(ba);
    			// to parse the byte buffer
    			vg = new VTDGen();
    			vg.setDoc(ba);
    			vg.parse(true);
    			vn = vg.getNav();
    			//
    			long startTime = System.nanoTime();
    			startTime = System.nanoTime();
    			long endTime = System.nanoTime();
    			//
    			HalModel.getMetadatas(vn);
     
    			endTime = System.nanoTime();
     
    			System.out.println("Total elapsed time in execution of method is :"
    					+ ((endTime - startTime)));
     
    		} catch (Exception e) {
    			System.err.println("exception occurred ==>" + e);
    		} finally {
    			try {
    				fis.read();
    				fis.close();
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    			fis = null;
    			f = null;
     
    			vg.clear();
    			vg = null;
    			vn = null;
    			Arrays.fill(ba, (byte) 0);
    			System.out.println(ba.length);
    			ba = null;
    		}
    	}
    Et la mémoire ne baisse pas d'un iota après le finally ...

    Si vous pouviez éclairer ma lanterne ...

  2. #2
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Il faudrait observer la mémoire avec VisualVM ou faire un jmap -histo pour savoir quels objets résident en mémoire à un moment donné.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Février 2010
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 17
    Par défaut
    Bonjour Nudger,

    Alors j'utilise MAT sous Eclipse qui me permet de visualiser la heap de la mémoire, et voici le dump de jmap -histo

    Object Histogram:

    Size Count Class description
    -------------------------------------------------------
    72114656 447015 char[]
    12136584 505691 java.lang.String
    5382224 45100 * ConstMethodKlass
    5367880 65737 java.lang.Object[]
    5075856 3386 int[]
    2680184 69832 * SymbolKlass
    2532440 45100 * MethodKlass
    2339320 3942 * ConstantPoolKlass
    2315304 32157 fr.***.**.model.Article
    1805600 3942 * InstanceKlassKlass
    1642496 3892 * ConstantPoolCacheKlass
    1628040 67835 java.util.HashMap$Entry
    1546008 64417 java.util.ArrayList
    1538768 27478 fr.***.**.model.Authors
    965232 60327 java.lang.Integer
    932096 4840 byte[]
    638352 831 java.util.HashMap$Entry[]
    442648 6324 short[]
    400416 4171 java.lang.Class
    297752 6095 * System ObjArray
    239640 81 float[]
    149824 2341 java.awt.event.InvocationEvent
    131376 2346 java.awt.event.ActionEvent
    109384 13 java.lang.ref.SoftReference[]
    72144 4509 java.lang.Character
    63336 2639 java.util.Hashtable$Entry
    58224 2426 java.lang.ref.WeakReference
    58064 191 * ObjArrayKlassKlass
    56280 2345 java.util.AbstractList$Itr
    [...]
    Mais je t'avouerai que ça ne me parle pas énormément ...
    Sachant que ce sont des métadatas que je parse et que je stocke les infos dans des arrayList, je créé ainsi des objets Authors/Article avec toutes les infos dont j'ai besoin

  4. #4
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Citation Envoyé par Javabi3n Voir le message
    Et la mémoire ne baisse pas d'un iota après le finally ...
    Et vous mesurez ça comment? Vous obtenez un out of memory error quand vous tentez de lire une deuxième fois le fichier? Et toutes ces mise à null ne servent à rien, au passage, puisque les variable en question n'existeront plus après la sortie de la méthode.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Février 2010
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 17
    Par défaut
    Bonjour tchize_,

    A l'aide de "top" et ce bout de code ,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void showMemoryUsage(Graphics2D g2d, int viewWidth, int viewHeight) {
    		totalMemRatio = (int) (Runtime.getRuntime().totalMemory() * 100 / maxMem);
    		usedMemRatio = (int) ((Runtime.getRuntime().totalMemory() - Runtime
    				.getRuntime().freeMemory()) * 100 / maxMem);
    		[...]
    	}
    Pour les null, je sais bien, mais on essaye un peu tout quand on ne sait pas quoi faire.

  6. #6
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    cette mesure (freememory) ne donne que la quantité de mémoire imémdiatement libre dans la jvm. Pas la quantité de mémoire potentiellement libre après un full GC.

    Le garbage collector vi sa propre vie en parallèle à l'application et c'est un gros fainéant. Tant qu'on ne risque pas de devoir allouer plsu de mémoire système, il va se la couler douce et faire très peu, car il n'y a pas nécessité de faire le nettoyage. Quand on a pas assez pour ne pas allouer de mémoire système, il va aller faire un gc de surface (nettoyer le plus facile à repérer). Et quand on risque le OutOfMemory error, il va faire un gc profond.

    Bref, exécutez 500 fois la méthode que vous avez montré avec le gros fichier, vous allez voir que la mémoire fluctue peu. C'est quand vous allez allouer votre deuxième gros byte[] que le gc va netoyer le premier.

  7. #7
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Il faut savoir que la désallocation des ressources mémoire ne rend pas forcément de mémoire au système.
    Donc cette méthode n'est pas bonne.

    Le principe de la gestion de la mémoire par une JVM est de prendre de la mémoire au système jusqu'à un certain seuil (paramètre -Xmx).
    A l'intérieur de cette mémoire attribuée à la JVM, une partie est consommée une partie est disponible.
    Quand le garbage collector se lance et libère de la mémoire, en général il ne rend rien au système, il ne fait que baisser la mémoire consommée et augmenter la mémoire disponible, mais la mémoire globale consommée par le processus java reste la même.

    Avec VisualVM, il est possible d'observer le comportement de la mémoire à l'intérieur de la JVM en temps réel, ce qui permet de voir réellement si la JVM est saturée ou non.

  8. #8
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    ce petit test pourrait vous être utile:
    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
    import java.util.Arrays;
    import java.util.Random;
     
    public class MemoryTest {
     
     
    	public static void main(String[] argv) throws InterruptedException{
    		Random r = new Random();
    		for (int i=0; i<150;i++){
    			int size = (r.nextInt(50)+10)*1024*1024; //entre 10M et 60M
    			allocate(size);
    			long total = Runtime.getRuntime().totalMemory();
    			long free = Runtime.getRuntime().freeMemory();
    			Runtime.getRuntime().gc(); // essayez sans			
    			displayMemory(free,total,Runtime.getRuntime().freeMemory(),Runtime.getRuntime().totalMemory());
    		}
    	}
    	public static void allocate(int size){
    		byte[] b = new byte[size];
    		Arrays.fill(b, (byte)69);
    	}
     
    	private static void displayMemory(long freeBefore, long totalBefore, long freeAfter,
    			long totalAfter) {
    		System.out.printf("before. Free: %04.2fM / %04.2fM (%04.2fM used)",((float)freeBefore)/(1024*1024),((float)totalBefore)/(1024*1024),((float)totalBefore-freeBefore)/(1024.0*1024));
    		System.out.printf("after.  Free: %04.2fM / %04.2fM (%04.2fM used)\n",((float)freeAfter)/(1024*1024),((float)totalAfter)/(1024*1024),((float)totalAfter-freeAfter)/(1024.0*1024));
    	}
    }
    A noter au passage que, personellement, je cherche toujours comment dire à la jvm de rendre la mémoire au système. bien qu'officiellement elle le fasse, le fait qu'elle tourne depuis 30 minute en me disant Before: Free: 281,40M / 281,63M (99,9%)(0,23M used) After: Free: 281,42M / 281,63M (99,9%)(0,21M used), j'ai un gros doute

  9. #9
    Membre Expert
    Avatar de professeur shadoko
    Homme Profil pro
    retraité nostalgique Java SE
    Inscrit en
    Juillet 2006
    Messages
    1 257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 76
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : retraité nostalgique Java SE

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 257
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    ce petit test pourrait vous être utile:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    public class MemoryTest {
    	public static void allocate(int size){
    		// etc. etc...
    	}
    renversant!

  10. #10
    Membre averti
    Profil pro
    Inscrit en
    Février 2010
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 17
    Par défaut
    Merci messieurs pour vos réponses, qui ont le méritent de m'éclaircir sur le fonctionnement souvent obscure de la gestion de mémoire.

    Nudger > Je vais tester VisualVM ( qui d'après ce que je vois s'intègre à Eclipse )

    tchize_ >Il est vrai que je n'ai pas d'"out of memory error", c'est donc que le garbage collector fait bien son travail, cependant au bout d'un certain temps d'utilisation, mon application se ralentie et cela devient gênant. Je pense que cela vient d'une mauvaise utilisation du cache ( en effet l'application permet de visualiser une large collection de documents au format PDFs issus du web ).

    merci encore pour vos éclaircissements !

    edit : tchize_ > Je vais de ce pas tester, je reviens vers vous par la suite.

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Février 2010
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 17
    Par défaut
    tchize_, le bout de code que vous m'avez pasté semble fonctionner

    before. Free: 1,76M / 50,95M (49,18M used)after. Free: 1,76M / 1,94M (0,18M used)
    before. Free: 1,76M / 39,95M (38,18M used)after. Free: 1,76M / 1,94M (0,18M used)
    before. Free: 1,76M / 19,95M (18,18M used)after. Free: 1,76M / 1,94M (0,18M used)

Discussions similaires

  1. Gros problème de consommation mémoire.
    Par Nyphel dans le forum Langage
    Réponses: 8
    Dernier message: 14/02/2007, 14h35
  2. Problème de mémoire avec BDE
    Par Machuet dans le forum Bases de données
    Réponses: 3
    Dernier message: 13/07/2004, 10h11
  3. Gros problème de session/cookies
    Par valfredr dans le forum XMLRAD
    Réponses: 18
    Dernier message: 03/06/2004, 09h21
  4. Problème de mémoire Affichage images
    Par Repti dans le forum C++Builder
    Réponses: 6
    Dernier message: 29/03/2004, 20h06
  5. Gros Problème avec DirectShow et la méthode RELEASE
    Par Olivier Delmotte dans le forum DirectX
    Réponses: 3
    Dernier message: 10/03/2003, 18h10

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