64 votes

Pourquoi attraper des exceptions en Java, alors que vous pouvez attraper des Throwables ?

Nous avons récemment rencontré un problème avec une application serveur Java. L'application lançait des erreurs qui n'étaient pas détectées parce que les erreurs sont une sous-classe distincte de Throwable et que nous ne détections que les exceptions.

Nous avons résolu le problème immédiat en attrapant les Throwables plutôt que les Exceptions, mais cela m'a fait réfléchir à la raison pour laquelle vous voudriez attraper des Exceptions plutôt que des Throwables, car vous manqueriez alors les Erreurs.

Donc, pourquoi vouloir attraper des exceptions alors que l'on peut attraper des Throwables ? ?

61voto

Ferdinand Beyer Points 27723

Extrait de la documentation de l'API Java :

La classe Exception et ses sous-classes sont une forme de Throwable qui indique les conditions qu'une application raisonnable pourrait vouloir attraper.

Un site Error est une sous-classe de Throwable qui indique des problèmes sérieux qu'une application raisonnable ne devrait pas essayer d'attraper.

Les erreurs sont généralement de bas niveau (par exemple, soulevées par la machine virtuelle) et ne doivent pas être détectées par l'application, car une poursuite raisonnable ne serait pas possible.

60voto

Neil Coffey Points 13408

Tout dépend un peu de ce que vous allez faire avec une erreur une fois que vous l'avez attrapée. En général, la capture d'une erreur ne doit pas être considérée comme faisant partie de votre flux d'exceptions "normal". Si vous en attrapez une, vous ne devriez pas penser à "continuer comme si rien ne s'était passé", parce que la JVM (et diverses bibliothèques) utiliseront les Erreurs comme un moyen de signaler que "quelque chose de vraiment sérieux s'est produit et que nous devons nous arrêter dès que possible". En général, il est préférable de les écouter lorsqu'elles vous disent que la fin est proche.

Un autre problème est que la récupération ou non d'une erreur peut dépendre de la machine virtuelle particulière, ce que vous pouvez ou non contrôler.

Cela dit, il existe quelques cas particuliers où il est sûr et/ou souhaitable de capturer les erreurs, ou du moins certaines sous-classes :

  • Il y a des cas où vous voulez vraiment arrêter le cours normal du flux : par exemple, si vous êtes dans une servlet, vous ne voulez peut-être pas que le gestionnaire d'exception par défaut du programme d'exécution de la servlet annonce au monde entier que vous avez eu une OutOfMemoryError, que vous puissiez ou non vous en remettre.
  • Occasionnellement, une erreur sera levée dans les cas où la JVM peut récupérer proprement la cause de l'erreur. Par exemple, si une erreur OutOfMemoryError se produit lors d'une tentative d'allocation d'un tableau, dans Hotspot au moins, il semble que vous puissiez vous en remettre en toute sécurité. (Il y a bien sûr d'autres cas où une OutOfMemoryError pourrait être lancée et où il n'est pas sûr d'essayer et de continuer).

En résumé, si vous attrapez un Throwable/Error au lieu d'une Exception, il faut que ce soit une un cas bien défini où vous savez que vous "faites quelque chose de spécial". .

Edit : Peut-être que c'est évident, mais j'ai oublié de le dire en pratique, la JVM pourrait ne pas invoquer votre clause "catch". sur une erreur. J'ai certainement vu Hotspot ignorer avec désinvolture les tentatives d'attraper certaines OutOfMemoryErrors et NoClassDefFoundError.

6voto

Craig P. Motlin Points 11814

En général, les erreurs sont des problèmes dont vous ne pouvez pas vous remettre, comme par exemple OutOfMemoryError . Il n'y a rien à faire en les attrapant, donc vous devriez généralement les laisser s'échapper, et mettre la machine virtuelle hors service.

6voto

Darron Points 13196

Beaucoup des autres réponses regardent les choses de façon trop étroite.

Comme on dit, si vous écrivez du code d'application, vous ne devriez pas attraper Throwable. Vous ne pouvez rien y faire, il est donc préférable de laisser le système environnant (JVM ou framework) gérer ces problèmes.

Cependant, si vous écrivez du "code système", comme un framework ou un autre code de bas niveau, vous pouvez très bien vouloir attraper Throwable. La raison est la suivante tentative pour signaler l'exception, peut-être dans un fichier journal. Dans certains cas, la journalisation échouera, mais dans la plupart des cas, elle réussira et vous disposerez des informations nécessaires pour résoudre le problème. Une fois votre tentative de journalisation effectuée, vous devez soit relancer, soit tuer le thread en cours, soit quitter toute la JVM.

5voto

Scott Stanchfield Points 15863

Je vais prendre un chemin légèrement différent des autres.

Il existe de nombreux cas où vous voudriez attraper Throwable (principalement pour enregistrer/rapporter que quelque chose de mal est arrivé).

Cependant vous devez être prudent et rejeter tout ce que vous ne pouvez pas gérer.

Ceci est particulièrement vrai pour ThreadDeath.

Si jamais vous attrapez Throwable, assurez-vous de faire ce qui suit :

try {
    ...
} catch (SomeExceptionYouCanDoSomethingWith e) {
    // handle it
} catch (ThreadDeath t) {
    throw t;
} catch (Throwable t) {
    // log & rethrow
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X