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

avec Java Discussion :

Java Heap Space : bien gérer l'exception


Sujet :

avec Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Expert confirmé
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 660
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 660
    Par défaut Java Heap Space : bien gérer l'exception
    bonjour,


    j'ai une application qui peut dans certains cas provoquer une erreur de type "java.lang.OutOfMemoryError: Java heap space". Je voudrais gérer convenablement cette erreur : dans mon cas il s'agirait de fermer simplement l'application.

    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
     
    try
    {
        // mon code qui provoque l'erreur
     
    }
    catch (OutOfMemoryError ex)
    {
    	JOptionPane.showMessageDialog(this, ex.getMessage(), "Critical Error.", JOptionPane.ERROR_MESSAGE);
    	Logger.getLogger(MonProjet.class.getName()).log(Level.SEVERE, null, ex);
    	System.gc();
    	System.exit(-1);
    }
    catch (Error ex)
    {
    	JOptionPane.showMessageDialog(this, ex.getMessage(), "Critical Error.", JOptionPane.ERROR_MESSAGE);
    	Logger.getLogger(MonProjet.class.getName()).log(Level.SEVERE, null, ex);
    	System.gc();
    	System.exit(-1);
    }
    catch(Exception ex)
    {
    	JOptionPane.showMessageDialog(this, ex.getMessage(), "Critical Error.", JOptionPane.ERROR_MESSAGE);
    	Logger.getLogger(MonProjet.class.getName()).log(Level.SEVERE, null, ex);
    	System.gc();
    	System.exit(-1);
    }

    Ce code fonctionne très bien mais toutefois, je voudrais savoir si ma manière dé gérer cette erreur est "propre", à savoir :
    - j'appelle le carbage collector (pour détruire les objets et vider la mémoire ) ;
    - je fais un exit(-1) : je ne devrais pas plutôt faire un dispose()


    pour vos conseils.

  2. #2
    Membre chevronné
    Inscrit en
    Juillet 2006
    Messages
    534
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 534
    Par défaut
    Bonjour,

    Normalement avec Java on n'a pas besoin de gc (c'est Java qui gere lui-meme ce genre de choses).

    Pour dispose: Java gere ca normalement tu n'as pas besoin de le faire.

    Quant au exit avec -1 si tu veux retourner un code de retour comme sous *nix.

  3. #3
    Membre chevronné Avatar de gronono
    Inscrit en
    Novembre 2003
    Messages
    457
    Détails du profil
    Informations personnelles :
    Âge : 43

    Informations forums :
    Inscription : Novembre 2003
    Messages : 457
    Par défaut
    Si tu as OutOfMemoryError, tu arrives encore à créer des objets ?

  4. #4
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par ttttnht Voir le message
    Normalement avec Java on n'a pas besoin de gc (c'est Java qui gere lui-meme ce genre de choses).
    +1
    Dans 99% des cas le System.gc() est contre-productif et peut engendrer de mauvaise performance... en plus d'être inutile !

    C'est le cas ici car le GC va faire tout son possible pour libérer la mémoire avant de remonter une OutOfMemoryError.
    Et à la fin de l'application la JVM libère toute la mémoire d'un bloc (ce qui est bien plus performant).


    Citation Envoyé par ttttnht Voir le message
    Quant au exit avec -1 si tu veux retourner un code de retour comme sous *nix.
    Le exit() suffit amplement pour fermer l'application et tous ses éléments graphiques. Il me semble toutefois qu'on utilise en général un code de retour positif, mais c'est un détail...

    Maintenant il est peut-être préférable de fermer explicitement certaines ressources qui pourrait se retrouver bloquer pendant un certain temps (comme une connexion réseau par exemple), mais il n'y a pas de problème pour tout ce qui concerne l'interface utilisateur...


    Mais au cas où tu tu peux utiliser les shutdown hook, qui seront exécuté juste avant la fin de ton application quelque soit la manière dont elle se termine :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    	Runtime.getRuntime().addShutdownHook(new Thread() {
    		@Override
    		public void run() {
    			//
    			System.out.println("Bye bye...");
    		}
    	});


    Citation Envoyé par gronono Voir le message
    Si tu as OutOfMemoryError, tu arrives encore à créer des objets ?
    Bonne remarque !

    En fait cela dépend de l'état de ton application. Prenons par exemple une application limité à 64Mo.

    Si tu utilises réellement 32Mo et que ton application tente d'allouer encore 40 Mo cela va provoquer une OutOfMemoryError, mais en sortie de cela ton application se retrouve à nouveau à 32Mo (les 40 n'ont pas pu être alloué) et tu peut donc allouer de nouveaux objets. Toutefois il n'est pas vraiment conseiller de continuer l'application comme si de rien n'était car il y a de forte chance que cela se reproduise...

    Maintenant si petit à petit ton application approche des 64Mo d'utilisation réelles, alors tu peux en effet rencontrer des problèmes à nouveau jusque dans le code de traitement de ton exception (par exemple car il n'y a toujours pas assez de mémoire pour le JOptionPane). Cela peut être problématique car alors le exit() ne serait pas exécuté, et l'application pourrait continuerait de tourner...

    En fait pour gérer ce cas extrême il faut utiliser un try/finally :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    	try {
    		JOptionPane.showMessageDialog(this, ex.getMessage(), "Critical Error.", JOptionPane.ERROR_MESSAGE);
    		Logger.getLogger(MonProjet.class.getName()).log(Level.SEVERE, null, ex);
    	} finally {
    		System.exit(1);
    	}



    Maintenant il y a deux point qui me gène dans ton code :
    • Les 3 blocs de traitement des exceptions identique !
    • Le fait que tu traites des Errors directement dans ton code.


    Les Errors correspondent à des problèmes graves, et ne devrait pas vraiment être traitées...

    Si tu es en Java 5.0 il est préférables d'utiliser les UncaughtExceptionHandler, qui te permettent de traiter les exceptions qui ne sont pas traitées :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    	Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
    		@Override
    		public void uncaughtException(Thread t, Throwable ex) {
    			try {
    				JOptionPane.showMessageDialog(this, ex.getMessage(), "Critical Error.", JOptionPane.ERROR_MESSAGE);
    				Logger.getLogger(MonProjet.class.getName()).log(Level.SEVERE, null, ex);
    			} finally {
    				System.exit(1);
    			}
    		}
    	});

    a++

  5. #5
    Expert confirmé
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 660
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 660
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Dans 99% des cas le System.gc() est contre-productif et peut engendrer de mauvaise performance... en plus d'être inutile !

    C'est le cas ici car le GC va faire tout son possible pour libérer la mémoire avant de remonter une OutOfMemoryError.
    Et à la fin de l'application la JVM libère toute la mémoire d'un bloc (ce qui est bien plus performant).
    ok donc je supprime l'appel à System.gc()


    Citation Envoyé par adiGuba Voir le message
    Le exit() suffit amplement pour fermer l'application et tous ses éléments graphiques. Il me semble toutefois qu'on utilise en général un code de retour positif, mais c'est un détail...

    Maintenant il est peut-être préférable de fermer explicitement certaines ressources qui pourrait se retrouver bloquer pendant un certain temps (comme une connexion réseau par exemple), mais il n'y a pas de problème pour tout ce qui concerne l'interface utilisateur...

    Justement mon application créé 2 thread. Ils seront détruits lors de l'appel de exit() ?
    Par ailleurs, si j'ai une connexion réseau et qu'une erreur comme celle-ci se produit, sera-t-elle fermée lors de l'appel de exit() ?



    Citation Envoyé par adiGuba Voir le message
    Maintenant si petit à petit ton application approche des 64Mo d'utilisation réelles, alors tu peux en effet rencontrer des problèmes à nouveau jusque dans le code de traitement de ton exception (par exemple car il n'y a toujours pas assez de mémoire pour le JOptionPane). Cela peut être problématique car alors le exit() ne serait pas exécuté, et l'application pourrait continuerait de tourner...

    En fait pour gérer ce cas extrême il faut utiliser un try/finally :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    	try {
    		JOptionPane.showMessageDialog(this, ex.getMessage(), "Critical Error.", JOptionPane.ERROR_MESSAGE);
    		Logger.getLogger(MonProjet.class.getName()).log(Level.SEVERE, null, ex);
    	} finally {
    		System.exit(1);
    	}

    Les Errors correspondent à des problèmes graves, et ne devrait pas vraiment être traitées...

    Si tu es en Java 5.0 il est préférables d'utiliser les UncaughtExceptionHandler, qui te permettent de traiter les exceptions qui ne sont pas traitées :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    	Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
    		@Override
    		public void uncaughtException(Thread t, Throwable ex) {
    			try {
    				JOptionPane.showMessageDialog(this, ex.getMessage(), "Critical Error.", JOptionPane.ERROR_MESSAGE);
    				Logger.getLogger(MonProjet.class.getName()).log(Level.SEVERE, null, ex);
    			} finally {
    				System.exit(1);
    			}
    		}
    	});
    Il n'y a pas de catch() dans tes exemples


    J'ai placé un finally{...} après le try et le exit est exécuté même si aucune erreur est levée... J'ai raté un truc ?

  6. #6
    Expert confirmé
    Avatar de Baptiste Wicht
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    7 431
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2005
    Messages : 7 431
    Par défaut
    Citation Envoyé par Auteur Voir le message
    Justement mon application créé 2 thread. Ils seront détruits lors de l'appel de exit() ?
    Oui, tout les threads sont détruits par exit().

    Citation Envoyé par Auteur Voir le message
    Par ailleurs, si j'ai une connexion réseau et qu'une erreur comme celle-ci se produit, sera-t-elle fermée lors de l'appel de exit() ?
    Non, c'est à toi de gérer ce cas-là, les ressources ne sont pas automatiquement fermées.

    Citation Envoyé par Auteur Voir le message
    Il n'y a pas de catch() dans tes exemples

    J'ai placé un finally{...} après le try et le exit est exécuté même si aucune erreur est levée... J'ai raté un truc ?
    Tu n'en a pas pas besoin.

    Il s'agit d'un try/finally. Ce qui va dire que ton exit(-1) sera éxécuté même si une erreur survient dans le corps du try, dans cet exemple s'il n'y a plus assez de mémoire pour créer un nouvel objet et pour éxécuter JOptionPane, ton programme va quand même correctement quitter.

  7. #7
    Expert confirmé
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 660
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 660
    Par défaut
    J'aurai peut-être dû le dire dès le début
    L'erreur "java.lang.OutOfMemoryError: Java heap space" se produit lorsque je remplis un JTextPane. Il arrive un moment où je ne peux plus écrire dans le composant car l'application ne dispose pas de mémoire suffisante.



    Citation Envoyé par adiGuba Voir le message
    Si tu es en Java 5.0 il est préférables d'utiliser les UncaughtExceptionHandler, qui te permettent de traiter les exceptions qui ne sont pas traitées :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    	Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
    		@Override
    		public void uncaughtException(Thread t, Throwable ex) {
    			try {
    				JOptionPane.showMessageDialog(this, ex.getMessage(), "Critical Error.", JOptionPane.ERROR_MESSAGE);
    				Logger.getLogger(MonProjet.class.getName()).log(Level.SEVERE, null, ex);
    			} finally {
    				System.exit(1);
    			}
    		}
    	});
    Ce bout de code m'intéresse bien Mais est-t-il possible de filtrer les exceptions qui seront gérées par ce thread ?
    En effet, la boite dialogue s'affiche et le programme quitte à la moindre exception levée ou non gérée (c'est le but me direz vous). Mais est-il possible de ne traiter que l'erreur Java Heap Space ?

  8. #8
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Il doit être énorme ton JTextPane





    Ce bout de code m'intéresse bien Mais est-t-il possible de filtrer les exceptions qui seront gérées par ce thread ?
    Tu peux "thrower" l'exception pour la recatcher

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    	Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
    		@Override
    		public void uncaughtException(Thread t, Throwable ex) {
    			try {
    				throw ex;
    			} catch(OutOfMemoryError e) {
    				// traitement OutOfMemoryError
    			} catch (Throwable t) {
    				// Autre traitement
    			}
    		}
    	});
    Par contre les autres exceptions qui arrive ici sont des erreurs inattendus, donc il n'y a pas vraiment de raison que tu les ignores. Cela pourrait même être "dangereux" en générant de plus en plus d'erreurs incompréhensible...


    a++

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

Discussions similaires

  1. Réponses: 10
    Dernier message: 25/08/2010, 21h07
  2. Réponses: 3
    Dernier message: 12/02/2010, 18h20
  3. Réponses: 8
    Dernier message: 12/02/2010, 12h51
  4. Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    Par Edna24 dans le forum Développement de jobs
    Réponses: 2
    Dernier message: 03/06/2009, 11h19
  5. Exception JAVA HEAP SPACE
    Par JauB dans le forum Tomcat et TomEE
    Réponses: 4
    Dernier message: 06/08/2007, 10h51

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