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

  1. #1
    Expert éminent sénior
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 648
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 648
    Points : 11 137
    Points
    11 137
    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 confirmé
    Inscrit en
    Juillet 2006
    Messages
    534
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 534
    Points : 562
    Points
    562
    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 confirmé Avatar de gronono
    Inscrit en
    Novembre 2003
    Messages
    456
    Détails du profil
    Informations personnelles :
    Âge : 42

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

  4. #4
    Expert éminent sénior
    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
    Points : 23 190
    Points
    23 190
    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 éminent sénior
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 648
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 648
    Points : 11 137
    Points
    11 137
    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 éminent sénior
    Avatar de Baptiste Wicht
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    7 431
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Suisse

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

    Informations forums :
    Inscription : Octobre 2005
    Messages : 7 431
    Points : 21 324
    Points
    21 324
    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 éminent sénior
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 648
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 648
    Points : 11 137
    Points
    11 137
    Par défaut
    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.
    oui mais là même s'il n'y a pas d'erreur dans le try, le finally est exécuté


    Citation Envoyé par Baptiste Wicht Voir le message
    Oui, tout les threads sont détruits par exit().

    Citation Envoyé par Auteur
    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.
    ah....
    Ma connexion réseau est gérée justement par les thread (à cause de la méthode accept() des objets socket qui est bloquante). Du coup je dois explicitement faire un avant l'appel de ma fonction exit() ?

    Dans mon premier message j'hésitais entre this.dispose() qui ferme mon application (en stoppant les thread également) et System.exit().
    Les deux méthodes sont équivalentes finalement ? J'ai l'impression qu'un System.exit() est plus "bourrin".

  8. #8
    Expert éminent sénior
    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
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Auteur Voir le message
    oui mais là même s'il n'y a pas d'erreur dans le try, le finally est exécuté
    C'est ce qu'on veut faire non : Afficher un message d'erreur et quitter proprement.

    Si l'application se retrouve dans un état si extrême qu'on n'arrive même pas à afficher le message d'erreur, on quittera quand même l'application.




    Citation Envoyé par Auteur Voir le message
    ah....
    Ma connexion réseau est gérée justement par les thread (à cause de la méthode accept() des objets socket qui est bloquante). Du coup je dois explicitement faire un avant l'appel de ma fonction exit() ?
    Le join() est inutile...
    Ce que tu peux faire c'est fermer la socket explicitement.

    Citation Envoyé par Auteur Voir le message
    Dans mon premier message j'hésitais entre this.dispose() qui ferme mon application (en stoppant les thread également) et System.exit().
    Les deux méthodes sont équivalentes finalement ? J'ai l'impression qu'un System.exit() est plus "bourrin".
    Tu peux faire les dispose() si tu veux, ainsi que toutes les libérations des ressources externes (sockets, JDBC, etc.), mais je pense qu'il est important de finir par un exit().

    Les dispose() permettent de libérer les ressources alloués aux éléments graphiques, et non pas de terminer l'application.

    Maintenant c'est vrai que lorsque tu n'as plus aucune fenêtre et que l'EDT est le seul thread non-daemon, il se termine de lui même et met fin à l'application. Mais il faut être sûr qu'il n'y a aucun autre thread vivant !

    Pourrais-tu garantir cela dans le cas d'un plantage de ton application ?


    a++

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    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 ?
    oui, tu as raté qu'on est dans le UncaughtExceptionHandler, qui traite toutes les exceptions qui sont remontées au delà de ton run(). Quand on est dans ce handler, ca signifie que le thread est déjà mort. On est donc déjà dans un cas critique, il est donc normal de vouloir quitter quoi qu'il arrive.



    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() ?
    Lorsqu'une application se termine, c'est le travail de l'OS de libérer toutes les ressource. Java ne va pase explicitement fermer tes sockets, tes fenetres, tes threads et te file handle. Pourtant, l'os va tout détruire comme un grand lorsque l'application quitte (plus de fenetre, plus de sockets, plus de threads, réattacher les fils à un autre parent, plus de threads). Une application ne peut pas garder des ressources au delà de sa durée de vie.

  10. #10
    Expert éminent sénior
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 648
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 648
    Points : 11 137
    Points
    11 137
    Par défaut
    Je viens de comprendre
    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);
    	}
    Je dois placer ce bout de code dans le catch
    J'avais simplement rajouté le finally après mon try{} catch{}


    Citation Envoyé par tchize_ Voir le message
    oui, tu as raté qu'on est dans le UncaughtExceptionHandler, qui traite toutes les exceptions qui sont remontées au delà de ton run(). Quand on est dans ce handler, ca signifie que le thread est déjà mort. On est donc déjà dans un cas critique, il est donc normal de vouloir quitter quoi qu'il arrive.
    ok


    Citation Envoyé par tchize_ Voir le message

    Lorsqu'une application se termine, c'est le travail de l'OS de libérer toutes les ressource. Java ne va pase explicitement fermer tes sockets, tes fenetres, tes threads et te file handle. Pourtant, l'os va tout détruire comme un grand lorsque l'application quitte (plus de fenetre, plus de sockets, plus de threads, réattacher les fils à un autre parent, plus de threads). Une application ne peut pas garder des ressources au delà de sa durée de vie.
    Donc pas besoin de fermer mes sockets explicitement ???

    Citation Envoyé par adiGuba
    Ce que tu peux faire c'est fermer la socket explicitement.
    Même si a priori c'est plus propre...

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par Auteur Voir le message


    Donc pas besoin de fermer mes sockets explicitement ???
    Non je vois d'ailleurs pas l'intéret de nettoyer explicitement quelque chose qui va quand meme etre nettoyé de la meme manière par l'OS quelques millisecondes plus tard.

    Maintenant, si t'as des protocoles spécifiques avec tes client tu peux les utiliserp our fermer "propremen" au niveau protocole plutot que de leur couper abuptement le cordon, mais c'est risqué (tu sais pas dans quel état est ta jvm)

  12. #12
    Membre averti
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    338
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2008
    Messages : 338
    Points : 402
    Points
    402
    Par défaut
    L'appel a System.gc() n'est pas direct c'est juste une directive, Après on ne sait pas quand exactement il va passer, pour cela vaut mieux attendre un petit instant pour lui donné une chance de passé. Voilà une autre façon de faire:
    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
    try
    {
        // mon code qui provoque l'erreur
     
    }
    catch (OutOfMemoryError ex)
    {
       System.gc();
        //Retenter plusieurs fois le même code. Si toujours la même erreur   alors on sort définitivement!	
    boolean error = true;
    for(int i=0; i< 10; i++) {
       try {
            Thread.sleep(500);
            //rééxécuter le même code
           error = false; 
           break;
        } catch(OutOfMemoryError me) {
        } catch(Exception ignored) {}
     }
    if (error)  {
    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);
     }
    }
    }
    catch (Throwable e)
    {
         //Comme l'a spécifié adiguba avec un try - finally
    }
     
    }

  13. #13
    Expert éminent sénior
    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
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Il ne faut pas utiliser System.gc() !!!!


    a++

  14. #14
    Expert éminent sénior
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 648
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 648
    Points : 11 137
    Points
    11 137
    Par défaut
    Plusieurs remarques sur ton code hibour (en dehors du fait que tu utilises System.gc()) :

    1- Si j'ai un heap memory qui me dis que je pourrais encore créer un entier i et un booléen error ?
    2- Es-tu sûr qu'attendre 500ms une action de la jvm est suffisant, puisqu'en théorie on ne sait jamais quand cette action aura lieu ?
    3- Quel intérêt de ré-exécuter le code qui a provoquer l'erreur ?

  15. #15
    Expert éminent sénior Avatar de Uther
    Homme Profil pro
    Tourneur Fraiseur
    Inscrit en
    Avril 2002
    Messages
    4 562
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Tourneur Fraiseur

    Informations forums :
    Inscription : Avril 2002
    Messages : 4 562
    Points : 15 493
    Points
    15 493
    Par défaut
    Je suis d'accord su le fait que le code d'attente de hibour ne sert a rien.

    La jvm fait systématiquement un GC complet avant de lancer une OutOfMemoryError.

  16. #16
    Membre averti
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    338
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2008
    Messages : 338
    Points : 402
    Points
    402
    Par défaut
    Puis-je avoir une référence de la spécification java qui dit que la JVM appel le GC juste avant de lancer un OutOfMemoryError!
    Le code que j'ai fourni s'inspire d'un code de l'API java que j'ai vu dans l'une des classe XXXBuffer (écrite par un Pro de SUN). Je suis assez certain que le fait de donner une chance au GC de faire le ménage de la mémoire peut libérer un espace mémoire du coup on peut retenter une allocation mémoire.

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    api java:
    public class OutOfMemoryError
    extends VirtualMachineError

    Thrown when the Java Virtual Machine cannot allocate an object because it is out of memory, and no more memory could be made available by the garbage collector.

    The name gc stands for "garbage collector". The virtual machine performs this recycling process automatically as needed, in a separate thread, even if the gc method is not invoked explicitly.
    Les classes de base java pour certaines sont vieille et n'ont pas été revisitées depuis les première versions de java, le GC au début n'était pas ce qu'il est maintenant, et les appel au gc avaient une justification au tout début. Maintenant ce n'est plus le cas.

    De plus, quelque part dans les specs, il est mentionné clairement la marche a suivre pour allouer de la mémoire, et ca stipuel clairement les étape suivies en interaction avec le gc. Tu y verra donc que, si t'as le outofmemory, c'est qu'il est vraiment pas possible de trouver la mémoire.

  18. #18
    Membre averti
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    338
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2008
    Messages : 338
    Points : 402
    Points
    402
    Par défaut
    tchize:La classe java.nio.XXXBuffer est une classe à partir de java 1.4 elle n'est pas si vieille.
    Ce que tu as fourni n'est qu'une javadoc c'est pas une Specification.

  19. #19
    Expert éminent sénior
    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
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Pourtant la javadoc de OutOfMemoryException est tout à fait correcte !

    Exécutes ce code avec l'option -verbose:gc pour suivre le comportement du GC :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    	public static void main(String[] args) throws Exception {
    		byte[] bytes = new byte[Integer.MAX_VALUE];
    	}
    Tu verras qu'il tente des FullGCs avant de remonter l'exception.





    Maintenant ce n'est pas parce que c'est utilisé dans uen code en provenance de chez Sun que c'est forcément correct ! Au contraire l'API comporte un paquet de bug ou de code incorrect !


    a++

  20. #20
    Membre averti
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    338
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2008
    Messages : 338
    Points : 402
    Points
    402
    Par défaut
    C'est clair qu'on ne peut pas allouer plus de mémoire qu'en on a à notre possession!
    Dans le cas d'une application il ya des objets (références) qui ne sont plus atteignable et que le gc peut récupérer. Si à un instant T on veut allouer une quantité de mémoire raisonnable (pas comme dans ton code) alors peut être le fait d'attendre un peu le GC ça peut aider à récupérer un peu de mémoire et du coup ça peut fonctionner..

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 3 123 DernièreDernière

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