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 consommation mémoire.


Sujet :

Langage Java

  1. #1
    Membre du Club
    Inscrit en
    Novembre 2006
    Messages
    157
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 157
    Points : 69
    Points
    69
    Par défaut Gros problème de consommation mémoire.
    Bonsoir !

    Voici une application des plus simplistes :
    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
    public class Main
    {
    	/*
    	 * Lancement de l'application.
    	 */
     
    	public static void main(String[] args) 
    	{
            javax.swing.SwingUtilities.invokeLater(new Runnable() 
            {
                public void run() 
                {
                	try {Thread.currentThread().sleep(3000);}catch(InterruptedException e){}
                	try {Thread.currentThread().sleep(3000);}catch(InterruptedException e){}
                	try {Thread.currentThread().sleep(3000);}catch(InterruptedException e){}
                	try {Thread.currentThread().sleep(3000);}catch(InterruptedException e){}
                	try {Thread.currentThread().sleep(3000);}catch(InterruptedException e){}
                	try {Thread.currentThread().sleep(3000);}catch(InterruptedException e){}
                	try {Thread.currentThread().sleep(3000);}catch(InterruptedException e){}
                	try {Thread.currentThread().sleep(3000);}catch(InterruptedException e){}
                	try {Thread.currentThread().sleep(3000);}catch(InterruptedException e){}
                	try {Thread.currentThread().sleep(3000);}catch(InterruptedException e){}
                	try {Thread.currentThread().sleep(3000);}catch(InterruptedException e){}
                }
            });		
    	}
    }
    Je produits l'application avec Eclipse, et j'inclues la librairie javamail.

    Je m'amuse simplement à mettre 10 fois en attente le thread de l'application, et à regarder la mémoire consommée sous Windows :
    . 11MO avec un JAR exécutable d'Eclipse
    . 14MO-19MO avec un FatJar exécutable d'Eclipse, éventuellement passé en .exe avec exe4j

    Pour peu que je colle une petite interface et quelques fonctions webmail (récupération de messages sur un serveur IMAP), je suis desuite à 25MO.

    Est-ce normal, et je n'y peux rien ?
    Est-ce dû à Eclipse, qui inclue toujours au projet la "JRE System Library [jre 1.6.0]" ?

    Je cherche à savoir si il y a une possibilité pour diminuer la consommation mémoire, ou si il va me falloir changer de langage de programmation .

    Merci pour votre aide

  2. #2
    Expert éminent sénior
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Points : 12 977
    Points
    12 977
    Par défaut
    Félicitations tu es le papa d'une jolie petite horreur: tu es en train de bloquer l'EDT (tu rentres dedans avec le SwingUtilities.invokeLater()) avec tes sleep => surconsommation de mémoire obligée....

    Lances plutôt des threads qui eux même feront des sleep ça ira mieux

    Pour fêter cette naissance je t'offre un joli lien: http://gfx.developpez.com/tutoriel/j...ing-threading/
    Hey, this is mine. That's mine. All this is mine. I'm claiming all this as mine. Except that bit. I don't want that bit. But all the rest of this is mine. Hey, this has been a really good day. I've eaten five times, I've slept six times, and I've made a lot of things mine. Tomorrow, I'm gonna see if I can't have sex with something.

  3. #3
    Membre du Club
    Inscrit en
    Novembre 2006
    Messages
    157
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 157
    Points : 69
    Points
    69
    Par défaut
    Merci Sinok, aujourd'hui j'en apprends des choses !

    Plus sérieusement je vais regarder ca de plus près, mais j'ai mis des sleep juste comme ca... Après plusieurs heures passées à observer le tout.
    Le même code qui fait de simples conections/déconnections au serveur de messagerie IMAP consomme entre 17MO et 19MO, sans thread, sans interface, sans sleep douteux ().

    Est-ce plausible, ou suis-je là aussi probablement en train de faire une grosse grosse boulette ?

    Merci mon tuteur préféré

  4. #4
    Membre du Club
    Inscrit en
    Novembre 2006
    Messages
    157
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 157
    Points : 69
    Points
    69
    Par défaut
    Petit UP.
    J'ai tenté d'améliorer le tout, sans succès.
    Finalement, je crée une simple TrayIcon avec un mouseListener, sans popupMenu ni aucune autre interface, pour voir ce qu'il se passait.

    Cette TrayIcon me consomme directement 13Mo-14MO de mémoire .

    J'utilise la JDK 6.0, sans faire appel à la librairie JDIC, grâce au java.awt.TrayIcon.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class Main
    {
    	/*
    	 * Lancement de l'application.
    	 */
    
    	public static void main(String[] args) 
    	{      		
            		// Lancement de l'applicatif par la mise en place
            		// de l'icone en barre des tâches
            		new Icone_et_Menu();	
    	}
    }
    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
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    import java.awt.*;
    import java.awt.event.*;
    import java.awt.AWTException;
    import java.awt.CheckboxMenuItem;
    import java.awt.MenuItem;
    import java.awt.PopupMenu;
    import java.awt.SystemTray;
    import java.awt.TrayIcon;
    import java.awt.Toolkit;
    import java.lang.String;
    import javax.swing.*;
    
    //-------------------------------------------------------------------------------
    public class Icone_et_Menu 
    implements MouseListener
    {
    	/*
    	 * Déclaration des objets d'interfaces utilisés par la TrayIcon
    	 */
    
    
    	// Acces aux icones du veilleur de messagerie   //("Sources/Icones/Passif.png");
    	//public static URL url = Icone_et_Menu.class.getClassLoader().getResource("Icones/Actif.png");
    	public static Image mon_icone_actif 	= Toolkit.getDefaultToolkit().getImage(Icone_et_Menu.class.getClassLoader().getResource("Icones/Actif.png"));
    	public static Image mon_icone_passif 	= Toolkit.getDefaultToolkit().getImage(Icone_et_Menu.class.getClassLoader().getResource("Icones/Passif.png"));
    	public static Image mon_icone_arret 	= Toolkit.getDefaultToolkit().getImage(Icone_et_Menu.class.getClassLoader().getResource("Icones/Arret.png"));  
    	public static Image mon_icone_bayonne 	= Toolkit.getDefaultToolkit().getImage(Icone_et_Menu.class.getClassLoader().getResource("Icones/Bayonne.png")); 
    	
    	public static int mode_service = 0; 	//0 = automatique, 1 = manuel
    	
    	// Variables d'etats du service et de l'icone affichée, pour faciliter les conditions IF/ELSE
    	public static int etat_service = 0; 	//0 = arret, 1 = actif, 2 = suspendu, 3 = signal
    	public static int etat_icone = 0; 		//0 = arret, 1 = actif, 2 = passif
    	
    	public static int etat_fenetre_duree = 0; 		// 0 = fermée, 1 = ouverte
    	public static int etat_fenetre_frequence = 0; 	// 0 = fermée, 1 = ouverte
    	
    	public static int mode_avertisseur = 1; //0 = avertir au premier nouveau message, 1 = avertir à chaque nouveau message
    											// (Mettre à jour le menu si cette valeur est modifiée manuellement)
    	public static int etat_avertisseur = 0; //0 = n'a pas encore avertit, a déjà avertit de l'arrivée de messages
    											//Utilisée lorsque l'utilisateur ne souhaite être avertit qu'à l'arrivée
    											//du premier nouveau message. Tant qu'il n'a pas consulté les nouveaux messages
    											//(= fin du mode signal), il ne sera plus avertit si il est dans ce mode.
    	
    	public static int frequence = 3;		// Fréquence de recherche de nouveaux messages, en minutes
    	
    	public static int mode_recherche = 0; 	// 0 = affiche tous les messages taggés 'non-lu' sur le serveur
    											// 1 = n'affiche que les messages nouveaux pour le serveur, qu'il n'a jamis diffusé
    	
    	public static int mode_visibilite = 1;	// 0 = afficher tous les nouveaux messages reçus
    											// 1 = ne pas afficher les messages déjà signalés,
    											// pour lesquels l'utilisateur ne souhaite plus etre avertit
    	public static int NB_nouveaux_messages_total = 0;
    	public static int NB_nouveaux_messages_visibles = 0;
    	
    	public static String page_webmail = "http://intranet.bayonne.fr";
    	public static String chemin_firefox = "D:/Program Files/Mozilla Firefox/firefox.exe";
    	public static int duree_pause_consultation = 15; // Durée, en minutes, de la mise en pause du veilleur de messagerie lors de la consultation des nouveaux messages sur le webmail
    	
    	// TrayIcon : icone de barre des tâches, coeur visuel de l'application
    	public static TrayIcon mon_trayIcon = null; 
    	public static String tooltip_normal = new String("Veilleur de messagerie :\n\nClic-gauche : contrôler l'arrivée de nouveaux messages.\nClic-droit : options.");
    	public static String tooltip_signal = new String("Veilleur de messagerie : nouveaux messages reçus.\n\nClic-gauche : voir les nouveaux messages.\nClic-droit : options.");
    
    	
    //	-------------------------------------------------------------------------------    
    	/*
    	 * Classe d'interface initialisant la TrayIcon.
    	 */
    	public Icone_et_Menu() 
    	{   	
    		// Si le systeme d'exploitation supporte les icones systemes
    		if (SystemTray.isSupported()) 
    		{
    			// On créé la "SystemTray" (Récupération de celle du système)
    			SystemTray tray = SystemTray.getSystemTray();
    
    			try 
    			{				
    				// Ajout de la TrayIcon dans la Tray
    				tray.add(get_mon_trayIcon()); 
    			} 
    			catch (AWTException ex) 
    			{}
    		}
    	}
    //	-------------------------------------------------------------------------------   
    	/*
    	 * Gestion de la TrayIcon : apparence, comportement, etc.
    	 */
    	private TrayIcon get_mon_trayIcon() 
    	{
    		if (mon_trayIcon == null) 
    		{	        
    			// Paramètres d'initialisation de la TrayIcon			
    			String mon_titre = new String("Veilleur de messagerie");
    
    			// Initialisation de la TrayIcon
    			mon_trayIcon = new TrayIcon(mon_icone_arret, mon_titre, null);
    
    			// Ajustement de l'apparence de la TrayIcon
    			mon_trayIcon.setToolTip(tooltip_normal);// Ajout du ToolTip au survol de la souris            
    			mon_trayIcon.setImageAutoSize(true); 	// Dimensionnement automatique de l'icone
    
    			// Ajout d'un écouteur d'évènements (en cas de clic simple sur la TrayIcon)
    			mon_trayIcon.addMouseListener(this);
    		}
    		return mon_trayIcon;
    	}
    //	-------------------------------------------------------------------------------	
    	/*
    	 * Permet de traiter les évènements relatifs aux clic de la souris.
    	 */
    	// Lorsque : Bouton pressé puis relaché (clic classique)
    	public void mouseClicked (MouseEvent evt)
    	{
    		// En cas de clic-gauche : SwingUtilities.isLeftMouseButton(evt)
    		// En cas de clic avec le bouton du milieu : SwingUtilities.isMiddleMouseButton(evt)
    		// En cas de clic-droit : SwingUtilities.isRightMouseButton(evt)		
    		if (SwingUtilities.isLeftMouseButton(evt)) 
    		{
    			// Etat = 0 : arret
    			// Etat = 1 : actif
    			// Etat = 2 : passif
    			// Etat = 3 : signal
    			
    			// On vérifie que l'état du service avant d'agir.
    			if(etat_service == 0 ) // Service arrêté
    			{
    				if (mode_service == 0) // mode automatique
    				{
    
    				}
    				else if (mode_service == 1) // mode manuel
    				{
    
    				}				
    			}			
    			else if(etat_service == 1) // Service démarré
    			{
    
    			}
    			else if(etat_service == 2) // Service suspendu
    			{
    				//Fonctions.Reprendre_service(); 
    				// Démarrer et rechercher les nouveaux messages mais en mode 0 : 
    				// ne prévient pas l'utilisateur s'il n'y a pas de nouveaux messages... 
    				// Destinée à la reprise de service automatique, en fin de suspension.
    				// On ne l'utilisera donc pas ici.
    
    			}
    			else if(etat_service == 3) // Service démarré et signalant de nouveaux messages
    			{
    			}
    		}
    		else if (SwingUtilities.isMiddleMouseButton(evt))
    		{
    
    		}
    	}		
    
    	// Gestionnaires d'évènement complémentaires à surcharger, 
    	// car la classe implémente MouseListener
    	public void mousePressed (MouseEvent evt) {}	// Lorsque : Composant pressé
    	public void mouseReleased (MouseEvent evt) {}	// Lorsque : Composant relaché
    	public void mouseEntered (MouseEvent evt) {}	// Lorsque : La souris entre dans la fenêtre de l'applet
    	public void mouseExited (MouseEvent evt) {}		// Lorsque : La souris sort de la fenêtre de l'applet
    }
    J'avoue que 14MO pour une icone en barre des tâches, ca me semble bizarre

  5. #5
    in
    in est déconnecté
    Membre expérimenté Avatar de in
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    1 612
    Détails du profil
    Informations personnelles :
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Avril 2003
    Messages : 1 612
    Points : 1 718
    Points
    1 718
    Par défaut
    je ne suis pas sûr de ce que je vais dire mais il me semble que la mémoire minimum allouée par défaut à la JVM est de 10 Mo.

    Peut être peux tu essayer de jouer avec le paramètre -Xms pour réduire cette taille ...
    "If email had been around before the telephone was invented, people would have said, 'Hey, forget email! With this new telephone invention I can actually talk to people!"

    Besoin d'une nouvelle méthode pour développer ? -> http://www.la-rache.com/

  6. #6
    Membre du Club
    Inscrit en
    Novembre 2006
    Messages
    157
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 157
    Points : 69
    Points
    69
    Par défaut
    D'accord, je vais creuser dans cette voie, mais ca me perturbe un peu... Car même si 10MO sont directement alloués à la JVM, mon application en requiert 14 : ca veut dire qu'elle prend les 10MO et qua ca ne lui suffit pas, non ?

  7. #7
    Expert éminent sénior
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Points : 12 977
    Points
    12 977
    Par défaut
    Attention la JVM occupe un taille incompressible en mémoire de toute façon.
    Hey, this is mine. That's mine. All this is mine. I'm claiming all this as mine. Except that bit. I don't want that bit. But all the rest of this is mine. Hey, this has been a really good day. I've eaten five times, I've slept six times, and I've made a lot of things mine. Tomorrow, I'm gonna see if I can't have sex with something.

  8. #8
    Membre du Club
    Inscrit en
    Novembre 2006
    Messages
    157
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 157
    Points : 69
    Points
    69
    Par défaut
    Ah... D'accord...

    Je viens de faire un test :
    - Je lance mon .exe et il consomme 14MO
    - Je lance ce projet sous NetBeans et son profiler : dans mon gestionnaires tâche apparait le java.exe à 14MO lui aussi.

    Toutefois le profiler de NetBeans m'indique :
    - Heap size = 5MO
    - Used Heap = 1MO

    Donc, d'après le profiler de NetBeans, la JVM allouerait 5MO à mon application.
    Mon application ne consommerait réelement que 1MO sur les 5MO qui lui sont alloués.

    Si j'interprète cela correctement, ca veut dire que :
    - Windows alloue 14MO à mon application.
    - Sur ces 14MO, seuls 5MO sont requis pour l'exécution de mon application au travers de la JVM (sachant que mon application requiert que la JDK 6.0 soit installée).
    - Sur ces 5MO, seul 1MO est vraiment utilisé.

    Puis-je en déduire que sur les 14MO alloués par Windows, je n'en utilise que 1MO et que les 13MO restants sont accessibes à d'autres applications ?
    Exemple : si une application à 14MO ferait ramer mon système (imaginons un vieil ordinateur a 64MO), la mienne pourrait quand même tourner sans le faire ramer ?

  9. #9
    Membre du Club
    Inscrit en
    Novembre 2006
    Messages
    157
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 157
    Points : 69
    Points
    69
    Par défaut
    J'ai ma réponse .

    En fait dans mes 14MO j'ai 2 mémoires différentes :
    - celle de l'application
    - celle de la JVM

    On peut controler leurs status avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    final MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
    System.out.println( "APPLICATION - "+memoryBean.getHeapMemoryUsage() );
    System.out.println( "JVM - "+memoryBean.getNonHeapMemoryUsage() + "\n\n" );
    On obtient quelque chose comme :
    APPLICATION - init = 0(0K) used = 889248(868K) committed = 5177344(5056K) max = 66650112(65088K)
    JVM - init = 12779520(12480K) used = 9154000(8939K) committed = 13271040(12960K) max = 100663296(98304K)
    D'après :
    http://java.sun.com/j2se/1.5.0/docs/...moryUsage.html
    init
    Represents the initial amount of memory (in bytes) that the Java virtual machine requests from the operating system for memory management during startup. The Java virtual machine may request additional memory from the operating system and may also release memory to the system over time. The value of init may be undefined.

    used
    Represents the amount of memory currently used (in bytes).

    committed
    Represents the amount of memory (in bytes) that is guaranteed to be available for use by the Java virtual machine. The amount of committed memory may change over time (increase or decrease). The Java virtual machine may release memory to the system and committed could be less than init. committed will always be greater than or equal to used.

    max
    Represents the maximum amount of memory (in bytes) that can be used for memory management. Its value may be undefined. The maximum amount of memory may change over time if defined. The amount of used and committed memory will always be less than or equal to max if max is defined. A memory allocation may fail if it attempts to increase the used memory such that used > committed even if used <= max would still be true (for example, when the system is low on virtual memory).
    Donc, pour cet exemple, la mémoire utilisée fut de : 0.868+8.939 = 9.807 MO.
    Le total de mémoire réservée fut de : 5.056 + 12.960 = 18.016 MO.
    O a donc 18.016 - 9.807 = 8.209 MO réservés et inutilisés, soit presque 50% de mémoire réservée en excès !

    Ce qui me rassure, c'est que comme précisé par Sun ci-dessus, la mémoire réservée pour l'application et/ou pour la JVM peut varier à tout moment en augmentant ou diminuant. J'ne déduis donc que si mon système a besoin de mémoire, et que la JVM en a en excès, alors la JVM en libèrera.

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

Discussions similaires

  1. Problème de consommation mémoire
    Par Wizard50 dans le forum Débuter
    Réponses: 14
    Dernier message: 08/08/2012, 11h31
  2. Gros problème de mémoire
    Par Javabi3n dans le forum Langage
    Réponses: 14
    Dernier message: 26/01/2011, 19h23
  3. Problème de consommation mémoire
    Par yanis97 dans le forum Websphere
    Réponses: 0
    Dernier message: 04/11/2010, 14h32
  4. Problème de consommation mémoire
    Par étoile de mer dans le forum C
    Réponses: 10
    Dernier message: 19/06/2010, 14h59
  5. Problème de trop grande consommation mémoire
    Par luckyvae dans le forum Général Java
    Réponses: 2
    Dernier message: 19/03/2008, 11h05

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