Est-il possible de construire un extrait de code en Java qui rendrait une hypothétique java.lang.ChuckNorrisException
inaccessible?
Les pensées qui me viennent à l'esprit utilisent par exemple des intercepteurs ou une programmation orientée aspect .
java
exception
exception-handling
aop
Max Charas
la source
la source
finalize()
?Réponses:
Je n'ai pas essayé cela, donc je ne sais pas si la JVM restreindrait quelque chose comme ça, mais peut-être pourriez-vous compiler du code qui lance
ChuckNorrisException
, mais au moment de l'exécution, fournissez une définition de classeChuckNorrisException
qui ne prolonge pas Throwable .MISE À JOUR:
Ça ne marche pas. Il génère une erreur de vérificateur:
MISE À JOUR 2:
En fait, vous pouvez le faire fonctionner si vous désactivez le vérificateur de code d'octet! (
-Xverify:none
)MISE À JOUR 3:
Pour ceux qui suivent de chez eux, voici le script complet:
Créez les classes suivantes:
Compiler les classes:
Courir:
Commentez "étend RuntimeException" et recompilez
ChuckNorrisException.java
uniquement :Courir:
Exécuter sans vérification:
la source
Object
place deThrowable
, alors? (Le compilateur ne le permettra pas, mais comme nous avons déjà désactivé le vérificateur, on pourrait peut-être pirater le bytecode pour le faire.)Après avoir réfléchi à cela, j'ai réussi à créer une exception inaccessible. J'ai choisi de le nommer
JulesWinnfield
, cependant, plutôt que Chuck, parce que c'est une exception mère-champignon-pose-nuage. De plus, ce n'est peut-être pas exactement ce que vous aviez en tête, mais cela ne peut certainement pas être capturé. Observer:Et voilà! Exception non interceptée.
Production:
Quand j'aurai un peu plus de temps, je verrai si je ne peux pas trouver autre chose aussi.
Vérifiez également ceci:
Provoque un débordement de pile - encore une fois, les exceptions restent non détectées.
la source
JulesWinfield
? Le système ne s'arrêtera-t-il pas brutalement avant d'être jeté?throw new Whatever()
est en réalité en deux parties:,Whatever it = new Whatever(); throw it;
et le système meurt avant d'atteindre la deuxième partie.class cn extends exception{private cn(){}}
Avec une telle exception, il serait évidemment obligatoire d'utiliser un
System.exit(Integer.MIN_VALUE);
du constructeur car c'est ce qui se passerait si vous leviez une telle exception;)la source
while(true){}
place deSystem.exit()
.System.exit()
de travailler en installant un gestionnaire de sécurité qui l'interdit. cela transformerait le constructeur en une exception différente (SecurityException), qui pourrait être interceptée.Tout code peut intercepter Throwable. Donc non, quelle que soit l'exception que vous créez, elle sera une sous-classe de Throwable et sera sujette à être interceptée.
la source
hang
lui - même tenté d'attraper ChuckNorrisException: P(Certes, techniquement, cette exception n'est jamais levée, mais un véritable
ChuckNorrisException
ne peut pas être levé - il vous lance en premier.)la source
Toute exception que vous lancez doit étendre Throwable, afin qu'elle puisse toujours être interceptée. La réponse est donc non.
Si vous voulez le rendre difficile à manipuler, vous pouvez remplacer les méthodes
getCause(), getMessage()
,getStackTrace()
,toString()
de jeter un autrejava.lang.ChuckNorrisException
.la source
catch(Throwable t)
que le stocke uniquement dans une variable, donc mes suggestions ne s'appliquent que dans le bloc suivant lorsque l'utilisateur veut faire face à l'exceptionMa réponse est basée sur l'idée de @ jtahlborn, mais c'est un programme Java pleinement fonctionnel , qui peut être empaqueté dans un fichier JAR et même déployé sur votre serveur d'applications préféré dans le cadre d'une application Web .
Tout d'abord, définissons la
ChuckNorrisException
classe afin qu'elle ne plante pas la JVM depuis le début (Chuck aime vraiment planter les JVM BTW :)Va maintenant en
Expendables
classe pour le construire:Et enfin la
Main
classe pour botter les fesses:Compilez-le et exécutez-le avec la commande suivante:
Vous obtiendrez la sortie suivante:
Pas de surprise - c'est un coup de pied rond après tout :)
la source
Dans le constructeur, vous pouvez démarrer un thread qui appelle à plusieurs reprises
originalThread.stop (ChuckNorisException.this)
Le thread pourrait intercepter l'exception à plusieurs reprises mais continuerait à le lancer jusqu'à ce qu'il meure.
la source
Non. Toutes les exceptions en Java doivent être de sous
java.lang.Throwable
- classe , et bien que ce ne soit pas une bonne pratique, vous pouvez intercepter tout type d'exception comme ceci:Voir le java.lang.Throwable documentation pour plus d'informations.
Si vous essayez d'éviter les exceptions vérifiées (celles qui doivent être explicitement gérées), vous souhaiterez sous-classer Error ou RuntimeException.
la source
En fait, la réponse acceptée n'est pas si agréable car Java doit être exécuté sans vérification, c'est-à-dire que le code ne fonctionnerait pas dans des circonstances normales.
AspectJ à la rescousse de la vraie solution !
Classe d'exception:
Aspect:
Exemple d'application:
Production:
la source
Une variante du thème est le fait surprenant que vous pouvez lever des exceptions vérifiées non déclarées à partir du code Java. Comme il n'est pas déclaré dans la signature des méthodes, le compilateur ne vous permet pas d'attraper l'exception elle-même, bien que vous puissiez l'attraper en tant que java.lang.Exception.
Voici une classe d'aide qui vous permet de lancer n'importe quoi, déclaré ou non:
throw SneakyThrow.sneak(new ChuckNorrisException());
Lance maintenant une exception ChuckNorrisException, mais le compilateur se plaint danssur la capture d'une exception qui n'est pas levée si ChuckNorrisException est une exception vérifiée.
la source
Les seuls
ChuckNorrisException
s en Java devraient êtreOutOfMemoryError
etStackOverflowError
.Vous pouvez réellement les "attraper" dans le sens où un
catch(OutOfMemoryError ex)
s'exécutera au cas où l'exception serait levée, mais ce bloc renverra automatiquement l'exception à l'appelant.Je ne pense pas que cela
public class ChuckNorrisError extends Error
fasse l'affaire, mais vous pouvez essayer. Je n'ai trouvé aucune documentation sur l'extensionError
la source
Is it possible to construct a snippet of code in java that would make a hypothetical java.lang.ChuckNorrisException uncatchable?
Oui, et voici la réponse: Concevez votre
java.lang.ChuckNorrisException
tel qu'il ne soit pas une instance dejava.lang.Throwable
. Pourquoi? Un objet non déployable est par définition inaccessible car vous ne pouvez jamais attraper quelque chose qui ne peut jamais être lancé.la source
java.lang.ChuckNorrisException
doivent être une exception, et encore moins jetablesVous pouvez garder ChuckNorris interne ou privé et l'encapsuler ou le faire glisser ...
try { doChuckAction(); } catch(ChuckNorrisException cne) { /*do something else*/ }
la source
Deux problèmes fondamentaux avec la gestion des exceptions en Java sont qu'il utilise le type d'une exception pour indiquer si une action doit être prise en fonction de celle-ci, et que tout ce qui prend une action en fonction d'une exception (c'est-à-dire "l'attraper" est supposé résoudre la condition sous-jacente. Il serait utile d'avoir un moyen par lequel un objet d'exception pourrait décider quels gestionnaires devraient exécuter, et si les gestionnaires qui ont exécuté jusqu'à présent ont suffisamment nettoyé les choses pour que la méthode actuelle satisfasse ses conditions de sortie. Bien que cela puisse être utilisé pour créer des exceptions "inaccessibles", deux utilisations plus importantes consisteraient à (1) créer des exceptions qui ne seront considérées comme gérées que lorsqu'elles sont détectées par un code qui sait réellement comment les traiter,
finally
FooException
pendant unfinally
bloc pendant le déroulement d'unBarException
, les deux exceptions doivent se propager dans la pile des appels; les deux doivent être capturables, mais le déroulement doit se poursuivre jusqu'à ce que les deux soient capturés). Malheureusement, je ne pense pas qu'il y aurait moyen de faire fonctionner le code de gestion des exceptions de cette manière sans casser les choses.la source
finally
bloc se nettoie d'une exception antérieure, il est fort possible que l'une ou l'autre exception, en l'absence de l'autre, soit quelque chose que le code devrait gérer et continuer, mais que manipuler l'un et ignorer l'autre serait mauvais. Il n'y a cependant aucun mécanisme pour produire une exception composite que les deux gestionnaires traiteraient.Foo
peut distinguer une exception quiFoo
s'est levée ou veut délibérément prétendre qu'elle s'est jetée, de celle quiFoo
ne s'attendait pas à se produire lorsqu'elle était appeler une autre méthode. Voilà à quoi devrait ressembler la notion d'exceptions «vérifiées».Il est facilement possible de simuler une exception non interceptée sur le thread actuel. Cela déclenchera le comportement normal d'une exception non interceptée et fera donc le travail sémantiquement. Cependant, cela n'arrêtera pas nécessairement l'exécution du thread actuel, car aucune exception n'est réellement levée.
Ceci est en fait utile dans des situations (très rares), par exemple lorsqu'une
Error
manipulation appropriée est requise, mais la méthode est invoquée à partir d'un framework capturant (et rejetant) anyThrowable
.la source
Appelez System.exit (1) dans le
finalize
, et jetez simplement une copie de l'exception de toutes les autres méthodes, afin que le programme se termine.la source