Question : Le traitement des exceptions en Java est-il réellement lent ?
Selon la sagesse conventionnelle, ainsi que de nombreux résultats de Google, la logique exceptionnelle ne devrait pas être utilisée pour le déroulement normal d'un programme en Java. Deux raisons sont généralement avancées,
- il est vraiment lent - même un ordre de grandeur plus lent que le code normal (les raisons invoquées varient),
y
- il est désordonné parce que les gens s'attendent à ce que seules les erreurs soient traitées dans du code exceptionnel.
Cette question porte sur le numéro 1.
A titre d'exemple, cette page décrit la gestion des exceptions Java comme étant "très lente" et établit un lien entre cette lenteur et la création de la chaîne de messages d'exception - "cette chaîne est ensuite utilisée pour créer l'objet d'exception qui est lancé. Ce n'est pas rapide". L'article Gestion efficace des exceptions en Java dit que "la raison de ceci est due à l'aspect de création d'objet de la gestion des exceptions, ce qui rend le lancement d'exceptions intrinsèquement lent". Une autre raison est que la génération de la trace de la pile est ce qui ralentit le processus.
Mes tests (avec Java 1.6.0_07, Java HotSpot 10.0, sur Linux 32 bits) indiquent que la gestion des exceptions n'est pas plus lente que le code normal. J'ai essayé d'exécuter une méthode dans une boucle qui exécute du code. À la fin de la méthode, j'utilise un booléen pour indiquer s'il faut retourner o lancez . De cette façon, le traitement réel est le même. J'ai essayé d'exécuter les méthodes dans des ordres différents et de calculer la moyenne des temps de test, pensant que cela pouvait être dû au réchauffement de la JVM. Dans tous mes tests, l'envoi était au moins aussi rapide que le retour, si ce n'est plus (jusqu'à 3,1 % plus rapide). Je suis tout à fait ouvert à la possibilité que mes tests soient erronés, mais je n'ai rien vu dans les échantillons de code, les comparaisons de tests ou les résultats depuis un an ou deux qui montre que la gestion des exceptions en Java est réellement lente.
Ce qui m'a conduit sur cette voie, c'est une API que je devais utiliser et qui lançait des exceptions dans le cadre de la logique de contrôle normale. Je voulais les corriger dans leur utilisation, mais je ne pourrai peut-être pas le faire. Devrai-je plutôt les féliciter pour leur esprit d'initiative ?
Dans le document Traitement efficace des exceptions Java dans la compilation juste-à-temps Les auteurs suggèrent que la seule présence de gestionnaires d'exceptions, même si aucune exception n'est levée, est suffisante pour empêcher le compilateur JIT d'optimiser correctement le code, ce qui le ralentit. Je n'ai pas encore testé cette théorie.
12 votes
Je sais que votre question ne concernait pas le point 2), mais vous devriez vraiment reconnaître que l'utilisation d'une exception pour le déroulement du programme n'est pas mieux que l'utilisation de GOTOs. Certaines personnes défendent les gotos, d'autres défendent ce dont vous parlez, mais si vous demandez à quelqu'un qui a implémenté et maintenu l'un ou l'autre pendant un certain temps, il vous dira que les deux sont des pratiques de conception pauvres et difficiles à maintenir (et il maudira probablement le nom de la personne qui a pensé être assez intelligente pour prendre la décision de les utiliser).
92 votes
Bill, prétendre que l'utilisation d'exceptions pour le déroulement du programme n'est pas meilleure que l'utilisation de GOTO n'est pas mieux que de prétendre que l'utilisation de conditionnels et de boucles pour le déroulement du programme n'est pas meilleure que l'utilisation de GOTO. C'est un faux-fuyant. Expliquez-vous. Les exceptions peuvent et sont utilisées efficacement pour le déroulement du programme dans d'autres langages. Le code Python idiomatique utilise régulièrement les exceptions, par exemple. Je peux et j'ai maintenu du code qui utilise les exceptions de cette manière (pas en Java cependant), et je ne pense pas qu'il y ait quelque chose d'intrinsèquement mauvais à cela.
5 votes
Notez que certains frameworks web utilisent les exceptions comme un moyen pratique de rediriger les données, par exemple l'interface de Wicket. RestartResponseException . Cela n'arrive que quelques fois par demande, généralement pas, et je peux difficilement imaginer un moyen plus pratique dans un cadre de composants orienté Java.
21 votes
L'utilisation d'exceptions pour le flux de contrôle normal est une mauvaise idée en Java car le choix du paradigme a été fait de cette façon . Lisez Bloch EJ2 - il affirme clairement que, je cite, (Point 57)
exceptions are, as their name implies, to be used only for exceptional conditions; they should never be used for ordinary control flow
- en donnant une explication complète et détaillée de la raison. Et c'était le gars qui a écrit Java lib. Par conséquent, c'est lui qui définit le contrat d'API des classes. /Je suis d'accord avec Bill K sur ce point.8 votes
Si un framework fait cela (utiliser des exceptions dans des conditions non exceptionnelles), il est défectueux et cassé par conception, en brisant le contrat de la classe Exception du langage. Ce n'est pas parce que certaines personnes écrivent du code minable qu'il est moins minable.
7 votes
Btw, ça m'inquiète beaucoup que le commentaire de mmalone ait obtenu autant de upvotes malgré le fait qu'il ait dit "Je ne pense pas qu'il y ait quelque chose d'intrinsèquement mauvais avec ça"... Bien que je comprenne la demande de référence qu'il a faite (bien que la référence soit assez évidente dans ce cas), cela m'attriste de voir des gens être d'accord avec lui, car cela ne fait que souligner à quel point l'"assurance qualité de la communauté" de SO s'est détériorée au fil du temps pour moi.
2 votes
Nul autre que le créateur de stackoverflow.com n'a déclaré que les exceptions étaient pires que les GOTO : joelonsoftware.com/items/2003/10/13.html
11 votes
Nul autre que le créateur de stackoverflow.com n'a tort au sujet des exceptions. La règle d'or du développement logiciel est de ne jamais rendre le simple complexe et difficile à manier. Il écrit : "Il est vrai que ce qui devrait être un simple programme de 3 lignes s'épanouit souvent en 48 lignes lorsque vous mettez en place un bon contrôle des erreurs, mais c'est la vie, ...". Il s'agit d'une recherche de pureté, pas de simplicité.
0 votes
Une des choses amusantes à propos de Java - nous nous préoccupons de quelque chose comme la performance d'un try/catch qui ralentit Java par un facteur ÉNORME - mais il serait toujours plus rapide que presque n'importe quel autre langage existant (à part le C et quelques ésotériques comme Fortran !?!). Même si vous utilisiez beaucoup les exceptions, vous ne ralentiriez pas à la vitesse de Python ; et quant à Ruby ??? Même si chaque instruction était basée sur des exceptions, vous ne pourriez pas être aussi lent. D'un autre côté, les exceptions conduisent à un code difficile à suivre et sont généralement un PITA, le mieux étant de les éviter autant que possible.
0 votes
Autrefois, l'alimentation de la trace de la pile était assez lente. D'après ce que j'ai compris, cela s'est amélioré de manière drastique autour de java 5-6-ish.
0 votes
OP devrait en exécuter après avoir poussé un millier de trames sur la pile, afin que les effets d'une plus grande trace de pile soient plus apparents.
0 votes
La question porte sur le "traitement" des exceptions, où l'alternative est très souvent un crash. On ne peut pas être beaucoup plus lent qu'un arrêt. Si vous envisagez d'utiliser les exceptions comme élément de contrôle du flux, comme l'a suggéré Bill K., assurez-vous simplement que personne d'autre n'ait à maintenir le code...