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 :

[Optimisation] Problème de fuite de mémoire


Sujet :

Langage Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Octobre 2006
    Messages
    191
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 191
    Par défaut [Optimisation] Problème de fuite de mémoire
    Bonjour,
    J'aimerais avoir votre avis sur le code suivant, je pense que j'ai une fuite de mémoire quelque part. en effet l'outil jvisualvm me donne les graphes suivant lorsque je lance mon programme.Nom : Capture.PNG
Affichages : 766
Taille : 61,2 Ko
    Comme vous voyez, l'activité du GC est à 0%, les max du heap utilisé est dans un sens croissant, avec le temps j'ai une exception de java heap space OutOfMemory.

    Ci dessous mon code, il consiste à chaque "itération" de spring schudeler de lancer la création d'un fichier excel.

    context-app.xml
    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
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:context="http://www.springframework.org/schema/context"
    	 xmlns:task="http://www.springframework.org/schema/task"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans 
    		http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    		http://www.springframework.org/schema/context
        	http://www.springframework.org/schema/context/spring-context-4.0.xsd
        	http://www.springframework.org/schema/task  
        	http://www.springframework.org/schema/task/spring-task-4.0.xsd">
     
    	<import resource="classpath:config/context-datasource.xml"/>
     
        <bean id="mainExample" class="com.spring.main.MainExample">
        	<property name="actorDao" ref="actorDao"></property>
        </bean>
    	<task:scheduled-tasks>
    		<task:scheduled ref="mainExample" method="selectActor" cron="*/2 * * * * *" />
    	</task:scheduled-tasks>
     
     
     
    </beans>
    context-datasource.xml
    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
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:batch="http://www.springframework.org/schema/batch" 
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans 
    		http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    		http://www.springframework.org/schema/context
        	http://www.springframework.org/schema/context/spring-context-4.0.xsd">
     
    	<context:property-placeholder location="classpath:config/global.properties"/>
     
    	<bean id="dataSource" class="org.apache.commons.dbcp.ManagedBasicDataSource" destroy-method="close">
    		<property name="driverClassName" value="${driver.class}" />
          	<property name="url" value="${url.datasource}" />
          	<property name="username" value="${username.datasource}" />
          	<property name="password" value="${password.datasource}" />
          	<property name="initialSize" value="${pool.init.size}"/>
        	<property name="maxActive" value="${pool.max.active}"/>
        	<property name="removeAbandoned" value="${pool.remove.abandoned}"/>
      	</bean>
     
      	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    		<property name="dataSource" ref="dataSource"></property>
    	</bean>
     
    	<bean id="actorDao" class="com.spring.main.ActorDao">
    	</bean>	
     
    </beans>
    Schudeler.java
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class Schudeler 
    {
        public static void main( String[] args )
        {
        	Logger logger = LoggerFactory.getLogger(Schudeler.class);
    		logger.info("Démarrage du schudeler ");
    		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:config/context-app.xml");
        }
    }
    MainnExample.java
    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
    package com.spring.main;
     
    import java.util.List;
    import java.util.Map;
    import java.util.Random;
     
    public class MainExample {
     
    	String[] dates =new String[]{"2018-06-03", "2018-05-27", "2018-05-30", "2018-05-28", "2018-05-29"};
     
    	private ActorDao actorDao;
     
    	public void setActorDao(ActorDao actorDao) {
    		this.actorDao = actorDao;
    	}
     
    	/**
             * 
             */
    	public void selectActor(){
    		if(actorDao!=null){
    			String date = dates[getRandomIndex(dates.length)];
    			List<Map<String, Object>> actors = actorDao.getListeActors(date);
    			if(actors!=null && actors.size() > 0){
    				System.out.println("Number of actors is : " + actors.size());
    				String filename = getFilename(date);
    				//Export XLS
    				XlsxItemWriter writer = new XlsxItemWriter(filename);
    				try {
    					writer.write(actors);
    					System.out.println("Actors with birthay : " + date);
    				} catch (Exception e) {
    					System.out.println(e.getMessage());
    				}
    			}
    		}
    	}
     
    	private String getFilename(String date){
    		String sdate = date.replaceAll("-", "");
    		StringBuilder sb = new StringBuilder("e:/export/");
    		sb.append(sdate);
    		sb.append(".xlsx");
    		return sb.toString();
    	}
     
    	private int getRandomIndex(int max){
    		int r = 0;
    		Random random = new Random();
    		r = random.nextInt(max);
    		return r;
    	}
     
    }
    ActorDao.java
    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
    package com.spring.main;
     
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    import java.util.Map;
     
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import org.springframework.jdbc.core.JdbcTemplate;
     
    import com.spring.beans.ActorBean;
     
    public class ActorDao {
     
    	public List<Map<String, Object>> getListeActors(String date){
    		List<Map<String, Object>> liste = null;
    		try(ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:config/context-datasource.xml")){
    			JdbcTemplate jdbcTemplate = (JdbcTemplate)ctx.getBean("jdbcTemplate");
    			liste = jdbcTemplate.queryForList("SELECT * FROM `actor` WHERE date(?)=birthay", date);
    		}
    		return liste;
    	}
    }
    XlsxItemWriter .java
    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
    package com.spring.main;
     
    import java.io.FileOutputStream;
    import java.util.List;
    import java.util.Map;
     
    import org.apache.poi.ss.usermodel.Cell;
    import org.apache.poi.ss.usermodel.Row;
    import org.apache.poi.ss.usermodel.Sheet;
    import org.apache.poi.ss.usermodel.Workbook;
    import org.apache.poi.xssf.streaming.SXSSFWorkbook;
     
    public class XlsxItemWriter {
     
    	private String outputFilename;
        private Workbook workbook;
        private int currRow = 0;
     
        public XlsxItemWriter(String _outputFilename) {
        	this.outputFilename = _outputFilename;
    	}
     
        private void createStringCell(Row row, String val, int col) {
            Cell cell = row.createCell(col);
            cell.setCellValue(val);
        }
     
        public void write(List<Map<String, Object>> items) throws Exception {
    		workbook = new SXSSFWorkbook(1000);
            workbook.createSheet();
    		Sheet sheet = workbook.getSheetAt(0);
    		for(Map<String, Object> map :  items){
    			int c = 0;
    			if(currRow==0){
    				Row row = sheet.createRow(currRow);
    				for(Object o : map.keySet()){
    			    	createStringCell(row, o!=null ? o.toString() : "", c);
    			    	c++;
    		    	}
    				currRow++;
    			}
    			Row row = sheet.createRow(currRow);
    			c = 0;
    			for(Object o : map.keySet()){
    		    	createStringCell(row, map.get(o)!=null ? map.get(o).toString() : "", c);
    		    	c++;
    	    	}
    			currRow++;
            }
    		FileOutputStream fos = new FileOutputStream(outputFilename);
            workbook.write(fos);
            fos.close();
            fos.flush();
    	}
     
    }
    En commentant l'appel à XlsxItemWriter, tout semble normal, donc c'est le code qui génère cette fuite de mémoire.
    Qu'est ce qui me manque pour rendre ce code performant ?

    Merci

  2. #2
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Billets dans le blog
    2
    Par défaut
    Salut,

    Essaye de libérer le "workbook" (méthode close). Et utilise un try-with-resource au lieu d'une simple séquence "ouverture/fermeture", pour le workbook et les FileOutputStream : en cas d'exception les ressources seront bien libérées.

    Et puis pourquoi utiliser un SXSSFWorkbook au lieu d'un XSSFWorkbook, alors que tu n'utilises pas les capacités de streaming ?
    Et déclare ta variable workbook locale à la méthode, pas membre de classe.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  3. #3
    Membre confirmé
    Inscrit en
    Octobre 2006
    Messages
    191
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 191
    Par défaut
    Merci joel.drigo pour le retour,
    Il y a une différence après l'implémentation de tes remarques.
    J'ai enlevé le pool de connexion, il n 'est pas nécessaire (création d'un x connexions chaque 2 secondes ça aussi induit des problèmes de performances)
    Je mets Résolu

  4. #4
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par casawi Voir le message
    J'ai enlevé le pool de connexion, il n 'est pas nécessaire (création d'un x connexions chaque 2 secondes ça aussi induit des problèmes de performances)
    Un pool de connexions c'est bien, seulement il ne doit pas créer de connexions toutes les 2 secondes. Il doit :
    1. créer des connexions à l'initialisation (démarrage)
    2. éventuellement créer des connexions au besoin, limitées par un maximum

    Normalement, elles ne sont libérées qu'à la fin de l'exécution.

    En plus, si un pool de connexions crée une fuite de mémoire, c'est qu'elles ne sont pas correctement libérées le cas échéant.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

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

Discussions similaires

  1. Problème de fuite de mémoire
    Par Sfaxiano dans le forum Général Java
    Réponses: 13
    Dernier message: 30/10/2010, 23h49
  2. Problème de fuite de mémoire
    Par mickael_moopenn dans le forum Débuter
    Réponses: 3
    Dernier message: 18/07/2008, 00h03
  3. Problème de fuite de mémoire avec GTK+
    Par gwenhael dans le forum GTK+
    Réponses: 15
    Dernier message: 03/01/2008, 16h22
  4. [C++] problème de fuite mémoire
    Par Cirdan Telemnar dans le forum C++
    Réponses: 26
    Dernier message: 16/06/2006, 10h16
  5. Problème de fuite mémoire sur un idFTP
    Par jeromelef dans le forum Composants VCL
    Réponses: 6
    Dernier message: 26/07/2005, 17h29

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