Java Language Fonctionnalités avancées des exceptions


Exemple

Cet exemple couvre certaines fonctionnalités avancées et cas d'utilisation des exceptions.

Examiner le callstack par programmation

Java SE 1.4

La principale utilisation des stacktraces d'exception est de fournir des informations sur une erreur d'application et son contexte, de sorte que le programmeur puisse diagnostiquer et résoudre le problème. Parfois, il peut être utilisé pour d'autres choses. Par exemple, une classe SecurityManager peut avoir besoin d'examiner la pile d'appels pour décider si le code qui effectue un appel doit être approuvé.

Vous pouvez utiliser des exceptions pour examiner la pile d'appels par programme de la manière suivante:

    Exception ex = new Exception();   // this captures the call stack
    StackTraceElement[] frames = ex.getStackTrace();
    System.out.println("This method is " + frames[0].getMethodName());
    System.out.println("Called from method " + frames[1].getMethodName());

Il y a quelques mises en garde importantes à ce sujet:

  1. Les informations disponibles dans un StackTraceElement sont limitées. Il n'y a pas plus d'informations disponibles que celles affichées par printStackTrace . (Les valeurs des variables locales dans le cadre ne sont pas disponibles.)

  2. Javadocs pour getStackTrace() indique qu'une machine virtuelle getStackTrace() est autorisée à laisser de côté les cadres:

    Certaines machines virtuelles peuvent, dans certaines circonstances, omettre un ou plusieurs cadres de pile de la trace de pile. Dans le cas extrême, une machine virtuelle qui ne dispose d'aucune information de suivi de pile concernant ce produit jetable est autorisée à renvoyer un tableau de longueur nulle à partir de cette méthode.

Optimiser la construction des exceptions

Comme mentionné ailleurs, la construction d'une exception est assez coûteuse car elle implique la capture et l'enregistrement d'informations sur tous les cadres de pile du thread en cours. Parfois, nous savons que cette information ne sera jamais utilisée pour une exception donnée; par exemple, le stacktrace ne sera jamais imprimé. Dans ce cas, il existe un truc d'implémentation que nous pouvons utiliser dans une exception personnalisée pour que les informations ne soient pas capturées.

Les informations sur les trames de pile nécessaires pour les stacktraces sont capturées lorsque les constructeurs Throwable appellent la méthode Throwable.fillInStackTrace() . Cette méthode est public , ce qui signifie qu'une sous-classe peut la remplacer. L'astuce consiste à remplacer la méthode héritée de Throwable par une méthode qui ne fait rien; par exemple

  public class MyException extends Exception {
      // constructors

      @Override 
      public void fillInStackTrace() {
          // do nothing
      }
  }

Le problème avec cette approche est qu'une exception qui remplace fillInStackTrace() ne peut jamais capturer la trace de la pile et est inutile dans les scénarios où vous en avez besoin.

Effacer ou remplacer le stacktrace

Java SE 1.4

Dans certains cas, le stacktrace d'une exception créée de manière normale contient des informations incorrectes ou des informations que le développeur ne souhaite pas révéler à l'utilisateur. Pour ces scénarios, Throwable.setStackTrace peut être utilisé pour remplacer le tableau d'objets StackTraceElement les informations.

Par exemple, les éléments suivants peuvent être utilisés pour ignorer les informations de pile d'une exception:

 exception.setStackTrace(new StackTraceElement[0]);

Suppression d'exceptions

Java SE 7

Java 7 a introduit la construction try-with-resources et le concept associé de suppression des exceptions. Considérez l'extrait suivant:

try (Writer w = new BufferedWriter(new FileWriter(someFilename))) {
    // do stuff
    int temp = 0 / 0;    // throws an ArithmeticException
}

Lorsque l'exception est levée, try appelle close() sur le w qui FileWriter toute sortie mise en mémoire tampon et fermera ensuite FileWriter . Mais que se passe-t-il si une IOException est lancée lors du vidage de la sortie?

Qu'est-ce qui se passe est que toute exception qui est levée lors du nettoyage d'une ressource est supprimée . L'exception est interceptée et ajoutée à la liste des exceptions supprimées de l'exception principale. Ensuite, le try-with-resources continuera avec le nettoyage des autres ressources. Enfin, l’exception primaire sera relancée.

Un modèle similaire se produit si une exception est générée lors de l'initialisation de la ressource ou si le bloc try termine normalement. La première exception lancée devient la principale exception, et celles qui découlent du nettoyage sont supprimées.

Les exceptions supprimées peuvent être extraites de l'objet exception primaire en appelant getSuppressedExceptions .