it-swarm-id.com

Apa itu pengecualian yang ditekan?

Sebuah komentar (oleh pengguna soc ) pada jawaban ke pertanyaan tentang pengoptimalan panggilan ekor menyebutkan bahwa Java 7 memiliki fitur baru yang disebut "pengecualian tertekan", karena "penambahan ARM" (dukungan untuk ARM CPU?).

Apa "pengecualian yang ditekan" dalam konteks ini? Dalam konteks lain, "pengecualian yang ditekan" akan menjadi pengecualian yang ditangkap dan kemudian diabaikan (jarang ide yang bagus); ini jelas sesuatu yang berbeda.

65
Raedwald

Saya percaya komentator merujuk adalah pengecualian yang semi-diabaikan ketika dilemparkan dalam blok finally implisit dari blok coba-dengan-sumber daya , dalam konteks yang sudah ada pengecualian dilempar dari blok try:

Pengecualian dapat dilempar dari blok kode yang terkait dengan pernyataan coba-dengan-sumber daya. Dalam contoh writeToFileZipFileContents, pengecualian dapat dilempar dari blok try, dan hingga dua pengecualian dapat dilemparkan dari pernyataan try-with-resources ketika mencoba untuk menutup objek ZipFile dan BufferedWriter. Jika pengecualian dilemparkan dari blok percobaan dan satu atau lebih pengecualian dilemparkan dari pernyataan coba-dengan-sumber daya, maka pengecualian-pengecualian yang dilemparkan dari pernyataan coba-dengan-sumber daya ditekan, dan pengecualian yang dilemparkan oleh blok adalah satu-satunya. yang dilemparkan oleh metode writeToFileZipFileContents. Anda dapat mengambil pengecualian yang ditekan ini dengan memanggil metode Throwable.getSuppressed dari pengecualian yang dilemparkan oleh blok try.

(Itu mengutip bagian yang disebut "Pengecualian yang Ditekan" dari halaman yang tertaut.)

50
Jon Skeet

Untuk mengklarifikasi kutipan dalam jawaban Jon, hanya satu pengecualian yang dapat dilemparkan dengan metode (per eksekusi) tetapi dimungkinkan, dalam kasus try-with-resources, untuk beberapa pengecualian yang harus dilemparkan. Misalnya satu mungkin dilemparkan ke dalam blok dan yang lain dilemparkan dari finally implisit yang disediakan oleh try-with-resources.

Kompiler harus menentukan yang mana yang akan "benar-benar" lempar. Ia memilih untuk membuang pengecualian yang dimunculkan dalam kode eksplisit (kode dalam blok try) daripada yang dilemparkan oleh kode implisit (blok finally). Oleh karena itu pengecualian yang dilemparkan ke blok implisit ditekan (diabaikan). Ini hanya terjadi dalam beberapa pengecualian.

56
John B

Sebelum Java7; Ada pengecualian yang dilemparkan ke dalam kode tetapi entah bagaimana diabaikan.

misalnya.)

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 {
}

Konstruktor baru dan dua metode baru ditambahkan ke kelas Throwable di JDK 7. Ini adalah sebagai berikut:

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

dengan pendekatan baru ini, kita dapat menangani pengecualian yang ditekan itu juga.

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 {
}

Di Java7 coba-dengan-sumber daya; pengecualian di AutoCloseable :: close () ditambahkan sebagai pengecualian tertekan secara default bersama dengan pengecualian coba.

Sadar juga bahwa ini berbeda dari pengecualian berantai (diperkenalkan dengan JDK 1.4 dan dimaksudkan untuk memungkinkan untuk melacak hubungan sebab akibat antara pengecualian dengan mudah.)

17

Pengecualian yang ditekan adalah pengecualian tambahan yang muncul dalam pernyataan coba-dengan-sumber daya ( diperkenalkan pada Java 7 ) ketika AutoCloseable sumber daya ditutup. Karena beberapa pengecualian dapat terjadi saat menutup sumber daya AutoCloseable, pengecualian tambahan dilampirkan ke pengecualian utama sebagai pengecualian yang ditekan .

Melihat bytecode dari sepotong kode sampel coba-dengan-sumber daya, standar penangan pengecualian JVM digunakan untuk mengakomodasi semantik coba-dengan-sumber daya.

9
Dan Cruz

Menyetujui kode di bawah ini:

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!");
       }
   }
}

Dengan semua baris Anda akan mendapatkan: Java.lang.RuntimeException: from finally!

Menghapus finally blok yang akan Anda dapatkan: Java.lang.RuntimeException: from catch!

Menghapus catch blok yang akan Anda dapatkan:

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

Saya pikir ini ada hubungannya dengan "fasilitas pengecualian berantai". Ini akan memengaruhi bagaimana pengecualian ditangani oleh fasilitas ini saat jejak tumpukan berevolusi. Dari waktu ke waktu pengecualian yang merupakan bagian dari kelompok pengecualian dirantai dapat ditekan. Lihat dokumentasi Throwable untuk detail lebih lanjut.

0

Anda dapat menekan Pengecualian di Java 6 juga (sedikit tipu yang terlibat),

Saya membuat sebuah utilitas yang secara transparan menangani penekanan penekan di Java 1.6 dan Java 1.7. Anda dapat menemukan implementasinya di sini

Yang Anda butuhkan hanyalah menelepon:

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

untuk menekan pengecualian, dan

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

untuk mendapatkan pengecualian dari Pengecualian, jika ada yang masih menggunakan Java 1.6

0
user2179737