Dans quelles situations faut-il attraper Java.lang.Error
sur une application?
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.
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.
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.
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.
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.
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.
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 deThrowable
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 .
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.
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.
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).
c'est assez pratique pour capturer Java.lang.AssertionError dans un environnement de test ...
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:
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.
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.
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é.
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