web-dev-qa-db-fra.com

Qu'est-ce qu'une exception supprimée?

Un commentaire (par l'utilisateur soc ) sur une réponse à ne question sur l'optimisation des appels de queue mentionne que Java 7 a une nouvelle fonctionnalité appelée "exceptions supprimées", en raison de "l'ajout d'ARM" (prise en charge de ARM CPU?).

Qu'est-ce qu'une "exception supprimée" dans ce contexte? Dans d'autres contextes, une "exception supprimée" serait une exception qui a été interceptée puis ignorée (rarement une bonne idée); c'est clairement quelque chose de différent.

65
Raedwald

Je crois que le commentateur fait référence à une exception qui est semi-ignorée lorsqu'elle est lancée dans le bloc implicite finally d'un bloc try-with-resources , dans le contexte d'un existant exception levée du bloc try:

Une exception peut être levée à partir du bloc de code associé à l'instruction try-with-resources. Dans l'exemple writeToFileZipFileContents, une exception peut être levée à partir du bloc try et jusqu'à deux exceptions peuvent être levées à partir de l'instruction try-with-resources lorsqu'elle essaie de fermer les objets ZipFile et BufferedWriter. Si une exception est levée à partir du bloc try et qu'une ou plusieurs exceptions sont levées à partir de l'instruction try-with-resources, alors ces exceptions levées à partir de l'instruction try-with-resources sont supprimées et l'exception levée par le bloc est celle levée par la méthode writeToFileZipFileContents. Vous pouvez récupérer ces exceptions supprimées en appelant la méthode Throwable.getSuppressed à partir de l'exception levée par le bloc try.

(Cela cite une section intitulée "Exceptions supprimées" de la page liée.)

50
Jon Skeet

Pour clarifier la citation dans la réponse de Jon, une seule exception peut être levée par une méthode (par exécution) mais il est possible, dans le cas d'un try-with-resources, pour que plusieurs exceptions soient levées. Par exemple, un peut être jeté dans le bloc et un autre peut être jeté à partir du finally implicite fourni par le try-with-resources.

Le compilateur doit déterminer lequel lancer "vraiment". Il choisit de lever l'exception levée dans le code explicite (le code dans le bloc try) plutôt que celle levée par le code implicite (le bloc finally). Par conséquent, les exceptions levées dans le bloc implicite sont supprimées (ignorées). Cela se produit uniquement dans le cas de plusieurs exceptions.

56
John B

Avant Java7; Il y a des exceptions levées dans le code mais elles ont été ignorées d'une manière ou d'une autre.

par exemple.)

public class SuppressedExceptions {
  public static void main(String[] args) throws Exception {
    try {
        callTryFinallyBlock();
    } catch (Exception e) {
        e.printStackTrace(); **//Only Finally Exception is Caught**
    }
  }

  private static void callTryFinallyBlock() throws Exception {
    try 
    {
        throw new TryException(); **//This is lost**
    }
    finally
    {
        FinallyException fEx = new FinallyException();
        throw fEx;
    }
  }
}

class TryException extends Exception {
}

class FinallyException extends Exception {
}

Un nouveau constructeur et deux nouvelles méthodes ont été ajoutés à la classe Throwable dans JDK 7. Ce sont les suivants:

Throwable.getSupressed(); // Returns Throwable[]
Throwable.addSupressed(aThrowable);

avec cette nouvelle approche, nous pouvons également gérer ces exceptions supprimées.

public class SuppressedExceptions {
  public static void main(String[] args) throws Exception {
    try {
        callTryFinallyBlock();
    } catch (Exception e) {
        e.printStackTrace();
        for(Throwable t: e.getSuppressed())
        {
            t.printStackTrace();
        }
    }
  }

  private static void callTryFinallyBlock() throws Exception {
    Throwable t = null;
    try 
    {
        throw new TryException();
    }
    catch (Exception e) {
        t = e;
    }
    finally
    {
        FinallyException fEx = new FinallyException();
        if(t != null)fEx.addSuppressed(t);
        throw fEx;
    }
  }
}

class TryException extends Exception {
}

class FinallyException extends Exception {
}

En Java7, essayez avec des ressources; l'exception à AutoCloseable :: close () est ajoutée comme exception supprimée par défaut avec l'exception try.

Sachez également que cela est différent de exceptions chaînées (ont été introduits avec JDK 1.4 et étaient destinés à permettre de suivre facilement les relations de cause à effet entre les exceptions.)

17
Kanagavelu Sugumar

exceptions supprimées sont des exceptions supplémentaires qui se produisent dans une instruction try-with-resources ( introduites dans Java 7 ) when AutoCloseable les ressources sont fermées. Comme plusieurs exceptions peuvent se produire lors de la fermeture des ressources AutoCloseable, des exceptions supplémentaires sont attachées à un exception principale en tant qu'exceptions supprimées .

En examinant le bytecode d'un exemple de code try-with-resources, les standards gestionnaires d'exceptions JVM sont utilisés pour s'adapter à la sémantique try-with-resources.

9
Dan Cruz

Concéder le code ci-dessous:

public class MultipleExceptionsExample {

   static class IOManip implements Closeable{
       @Override
       public void close() {
           throw new RuntimeException("from IOManip.close");
       }
   }

   public static void main(String[] args) {
       try(IOManip ioManip = new IOManip()){
           throw new RuntimeException("from try!");
       }catch(Exception e){
           throw new RuntimeException("from catch!");
       }finally{
           throw new RuntimeException("from finally!");
       }
   }
}

Avec toutes les lignes, vous obtiendrez: Java.lang.RuntimeException: from finally!

En supprimant le bloc finally, vous obtiendrez: Java.lang.RuntimeException: from catch!

En supprimant le bloc catch, vous obtiendrez:

Exception in thread "main" Java.lang.RuntimeException: from try!
    Suppressed: Java.lang.RuntimeException: from IOManip.close
6
Adil

Je pense que cela a à voir avec la "facilité d'exception chaînée". Cela affectera la façon dont une exception est gérée par cette fonction à mesure que la trace de la pile évolue. Au fil du temps, les exceptions qui font partie d'un groupe d'exceptions chaînées peuvent être supprimées. Regardez la documentation Throwable pour plus de détails.

0

ARM - Automatic Resource Management (Introduit depuis Java 7)

Prenons un exemple très simple

static String readFirstLineFromFileWithFinallyBlock(String path)
                                                     throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(path));
    try {
        return br.readLine();
    } finally {
        if (br != null) br.close();
    }
}

Maintenant, si la fonction readLine() lève une exception, puis que la fonction close() [dans le bloc enfin] lève une exception, la dernière reçoit plus de priorité et est renvoyée à la fonction appelante. Dans ce cas, la Exception thrown by the readLine() method is ignored/suppressed. Vous pouvez enchaîner l'exception causante dans votre exception et renvoyer votre exception du bloc enfin.

Étant donné que Java 7, Une fonctionnalité a été fournie pour récupérer les exceptions supprimées. Vous pouvez appeler la fonction public final Java.lang.Throwable[] getSuppressed() sur l'objet jetable intercepté pour afficher les exceptions supprimées.

Par exemple.

static String readFirstLineFromFileWithFinallyBlock(String path)
        throws Exception {
    try (BufferedReader br = new BufferedReader(new FileReader(path));) {
        return br.readLine();
    }
}

Maintenant, si la ligne br.readLine(); lance Exception1 Et laisse ensuite dire que Exception2 Est levé lors de la fermeture de la ressource ] puis Exception1 supprime Exception2.

Quelques points à noter ici -

  1. Si le bloc try-with-resource lève une exception, c'est-à-dire pendant l'instanciation de la ressource, alors le bloc try ne s'exécutera pas et la même exception sera levée.
  2. Si l'instanciation de la ressource réussit, le bloc try lance une exception et une exception est levée lors de la fermeture de la ressource, puis l'exception levée lors de la fermeture de la ressource est supprimée par l'exception levée du bloc try.
  3. Si vous fournissez un bloc finalement explicite et qu'une exception est levée à partir de ce bloc, il supprimera toutes les autres exceptions. (Ce bloc explicite finalement s'exécute après la fermeture des ressources)

J'ai compilé la plupart des scénarios possibles avec des extraits de code et une sortie dans le post suivant.

Exceptions supprimées dans Java 7

J'espère que ça t'as aidé.

0
Aniket Thakur

Vous pouvez supprimer les exceptions dans Java 6 également (un peu de ruse),

J'ai créé un utilitaire qui gère de manière transparente la suppression des exceptions dans Java 1.6 et Java 1.7. Vous pouvez trouver l'implémentation ici

Il vous suffit d'appeler:

public static <T extends Throwable> T suppress(final T t, final Throwable suppressed) 

pour supprimer une exception, et

public static Throwable [] getSuppressed(final Throwable t) {

pour obtenir les exceptions supprimées d'une exception, au cas où quelqu'un utiliserait toujours Java 1.6

0
user2179737