web-dev-qa-db-fra.com

Quand faut-il attraper Java.lang.Error?

Dans quelles situations faut-il attraper Java.lang.Error sur une application?

108
João

Généralement jamais. Cependant, vous devez parfois détecter des erreurs spécifiques.

Si vous écrivez du code framework-ish (chargement de classes tierces), il peut être judicieux d'attraper LinkageErrors (aucune définition de classe trouvée, lien non satisfait, changement de classe incompatible). J'ai également vu du code tiers stupide émettre des sous-classes d'Erreurs. Vous devrez donc les gérer non plus.

En passant, je ne suis pas sûr qu'il ne soit pas possible de récupérer à partir de OutOfMemory.

96
Yoni Roit

Jamais. Vous ne pouvez jamais être sûr que l'application est capable d'exécuter la ligne de code suivante. Si vous obtenez un OutOfMemoryError, vous avez aucune garantie que vous pourrez faire quoi que ce soit de manière fiable . Attrapez RuntimeException et les exceptions vérifiées, mais jamais les erreurs.

http://pmd.sourceforge.net/rules/strictexception.html

50
tronda

Généralement, vous devriez toujours attraper Java.lang.Error et écrivez-le dans un journal ou affichez-le à l'utilisateur. Je travaille au support et vois tous les jours que les programmeurs ne peuvent pas dire ce qui s'est passé dans un programme.

Si vous avez un thread démon, vous devez empêcher son arrêt. Dans d'autres cas, votre application fonctionnera correctement.

Vous ne devriez attraper que Java.lang.Error au plus haut niveau.

Si vous regardez la liste des erreurs, vous verrez que la plupart peuvent être traitées. Par exemple, un ZipError se produit lors de la lecture de fichiers Zip corrompus.

Les erreurs les plus courantes sont OutOfMemoryError et NoClassDefFoundError, qui sont dans la plupart des cas des problèmes d’exécution.

Par exemple:

int length = Integer.parseInt(xyz);
byte[] buffer = new byte[length];

peut produire un OutOfMemoryError mais c’est un problème d’exécution et aucune raison de mettre fin à votre programme.

NoClassDefFoundError survient principalement si une bibliothèque n'est pas présente ou si vous travaillez avec une autre version Java). S'il s'agit d'une partie optionnelle de votre programme, vous ne devez pas le terminer.

Je peux donner beaucoup d’autres exemples de la raison pour laquelle c’est une bonne idée d’attraper Throwable au plus haut niveau et de produire un message d’erreur utile.

16
Horcrux7

Dans un environnement multithread, vous voulez le plus souvent l'attraper! Lorsque vous l'attrapez, connectez-le et mettez fin à l'application! Si vous ne le faites pas, un fil pouvant faire une partie cruciale serait mort, et le reste de l'application penserait que tout est normal. En dehors de cela, de nombreuses situations indésirables peuvent se produire. Un des plus petits problèmes est que vous ne pourriez pas trouver facilement la racine du problème si d'autres threads lançaient des exceptions à cause d'un thread qui ne fonctionnait pas.

Par exemple, la boucle devrait normalement être:

try {
   while (shouldRun()) {
       doSomething();
   }
}
catch (Throwable t) {
   log(t);
   stop();
   System.exit(1);
}

Même dans certains cas, vous voudriez traiter différentes erreurs différemment, par exemple, sur OutOfMemoryError, vous pourrez fermer l'application régulièrement (même peut-être libérer de la mémoire et continuer), sur d'autres, vous ne pouvez pas faire grand-chose.

14
Sarmun

Très rarement.

Je dirais seulement au plus haut niveau d'un thread afin d'ATTEMPT d'envoyer un message avec la raison de la mort d'un thread.

Si vous êtes dans un cadre qui fait ce genre de chose pour vous, laissez-le au cadre.

8
Darron

Presque jamais. Les erreurs sont conçues pour être des problèmes que les applications ne peuvent généralement pas résoudre. La seule exception pourrait être de gérer la présentation de l'erreur, mais même cela pourrait ne pas se dérouler comme prévu en fonction de l'erreur.

6
nicerobot

Un Error ne devrait généralement pas être attrapé , car il indique une condition anormale qui ne devrait jamais se produire .

De la Java) pour la classe Error :

Un Error est une sous-classe de Throwable qui indique de graves problèmes qu'une application raisonnable ne devrait pas essayer de résoudre. La plupart de ces erreurs sont des conditions anormales. [...]

Une méthode n'est pas obligée de déclarer dans sa clause throws les sous-classes d'erreur susceptibles d'être émises lors de l'exécution de la méthode mais non interceptées, car ces erreurs sont des conditions anormales qui ne devraient jamais se produire.

Comme le spécifie la spécification, un Error n'est jeté que dans des circonstances réelles. Quand un Error se produit, l'application ne peut que très peu faire et, dans certains cas, le Java La machine virtuelle elle-même peut être dans un état instable (telle que VirtualMachineError )

Bien qu'un Error soit une sous-classe de Throwable, cela signifie qu'il peut être attrapé par un try-catch, mais ce n’est probablement pas vraiment nécessaire, car l’application sera dans un état anormal lorsqu’un Error sera lancé par la JVM.

Il existe également une courte section sur ce sujet dans la section 11.5 La hiérarchie des exceptions de Spécification du langage Java, 2e édition .

6
coobird

Si vous êtes assez fou pour créer un nouveau framework de test unitaire, votre exécuteur de tests devra probablement intercepter Java.lang.AssertionError émis par un scénario de test.

Sinon, voir les autres réponses.

6
noahlz

Et il y a quelques autres cas où si vous attrapez une erreur, vous devez la relancer. Par exemple, ThreadDeath ne devrait jamais être attrapé, cela peut causer de gros problèmes si vous l'attrapez dans un environnement confiné (par exemple, un serveur d'applications):

Une application ne doit intercepter les instances de cette classe que si elle doit être nettoyée après avoir été terminée de manière asynchrone. Si ThreadDeath est attrapé par une méthode, il est important de le relancer afin que le thread meure réellement.

5
Guillaume

Très, très rarement.

Je ne l'ai fait que pour un cas très très connu. Par exemple, Java.lang.UnsatisfiedLinkError peut être renvoyé si deux indépendance ClassLoader charge la même DLL. (Je conviens que je devrais déplacer le fichier JAR vers un chargeur de classe partagé)

Mais le cas le plus courant est que vous deviez vous connecter pour savoir ce qui se passait lorsque l'utilisateur venait se plaindre. Vous voulez un message ou un popup à l'utilisateur, plutôt que silencieusement mort.

Même les programmeurs en C/C++, ils font apparaître une erreur et disent quelque chose que les gens ne comprennent pas avant de quitter (par exemple, une défaillance de la mémoire).

4
Dennis C

c'est assez pratique pour capturer Java.lang.AssertionError dans un environnement de test ...

3
Jono

Dans une Android, j'attrape un Java.lang.VerifyError . Une bibliothèque que j'utilise ne fonctionnera pas dans les appareils dotés d'une ancienne version du système d'exploitation et le code de la bibliothèque générera une telle erreur. Je pourrais bien sûr l'éviter en vérifiant la version du système d'exploitation au moment de l'exécution, mais:

  • Le SDK le plus ancien pris en charge peut changer à l'avenir pour la bibliothèque en question
  • Le bloc d'erreur try-catch fait partie d'un mécanisme de repli plus important. Certains périphériques spécifiques, bien qu'ils soient supposés supporter la bibliothèque, génèrent des exceptions. J'attrape VerifyError et toutes les exceptions d'utiliser une solution de secours.
3
kgiannakakis

Idéalement, nous ne devrions pas gérer/attraper les erreurs. Mais il peut y avoir des cas où nous devons le faire, en fonction des exigences du cadre ou de l'application. Disons que j'ai un démon XML Parser qui implémente DOM Parser qui consomme plus de mémoire. S'il existe une exigence telle que le fil d'analyse ne doit pas être désactivé lorsqu'il reçoit OutOfMemoryError, il doit plutôt la gérer et envoyer un message/courrier à l'administrateur de l'application/framework.

2
user3510364

Il y a une erreur lorsque la machine virtuelle Java ne fonctionne plus comme prévu ou sur le point de l'être. Si vous détectez une erreur, rien ne garantit que le bloc catch fonctionnera, et encore moins qu'il se poursuivra jusqu'au bout.

Cela dépendra également de l'ordinateur en cours d'exécution, de l'état actuel de la mémoire, il n'y a donc aucun moyen de tester, d'essayer et de faire de votre mieux. Vous n'aurez qu'un résultat hasardeux.

Vous réduirez également la lisibilité de votre code.

1
Nicolas Zozol

idéalement, nous ne devrions jamais capturer Error dans notre Java application, car il s’agit d’une condition anormale. L’application serait dans un état anormal et risquerait d’aboutir à un grave ou à un résultat erroné.

1
Vivek

Il peut être approprié de détecter une erreur dans les tests unitaires vérifiant qu'une assertion est faite. Si quelqu'un désactive les assertions ou supprime l'assertion, vous voudriez le savoir

1
Chanoch