Jawaban:
Umumnya tidak pernah.
Namun, terkadang Anda perlu menangkap kesalahan tertentu.
Jika Anda menulis kode framework-ish (memuat kelas pihak ketiga), mungkin bijaksana untuk menangkapnya LinkageError
(tidak ditemukan kelas def, link tidak puas, perubahan kelas tidak kompatibel).
Saya juga telah melihat beberapa kode pihak ketiga yang bodoh melempar subkelas Error
, jadi Anda harus menanganinya juga.
Ngomong-ngomong, saya tidak yakin itu tidak mungkin pulih OutOfMemoryError
.
Tidak pernah. Anda tidak pernah bisa yakin bahwa aplikasi dapat mengeksekusi baris kode berikutnya. Jika Anda mendapatkan OutOfMemoryError
, Anda tidak memiliki jaminan bahwa Anda akan dapat melakukan apa pun dengan andal . Tangkap RuntimeException dan periksa Pengecualian, tetapi jangan pernah Kesalahan.
boolean assertionsEnabled = false; assert assertionsEnabled = true;
Umumnya Anda harus selalu menangkap java.lang.Error
dan menulisnya ke log atau menampilkannya kepada pengguna. Saya bekerja sebagai pendukung dan melihat setiap hari bahwa programmer tidak dapat mengetahui apa yang telah terjadi dalam suatu program.
Jika Anda memiliki utas daemon maka Anda harus mencegahnya dihentikan. Dalam kasus lain, aplikasi Anda akan berfungsi dengan benar.
Anda seharusnya hanya menangkap java.lang.Error
di level tertinggi.
Jika Anda melihat daftar kesalahan, Anda akan melihat bahwa sebagian besar kesalahan dapat ditangani. Misalnya ZipError
terjadi saat membaca file zip yang rusak.
Kesalahan paling umum adalah OutOfMemoryError
dan NoClassDefFoundError
, yang dalam banyak kasus merupakan masalah runtime.
Sebagai contoh:
int length = Integer.parseInt(xyz);
byte[] buffer = new byte[length];
dapat menghasilkan OutOfMemoryError
tetapi ini adalah masalah runtime dan tidak ada alasan untuk menghentikan program Anda.
NoClassDefFoundError
terjadi terutama jika perpustakaan tidak ada atau jika Anda bekerja dengan versi Java lain. Jika ini adalah bagian opsional dari program Anda, maka Anda tidak boleh menghentikan program Anda.
Saya dapat memberikan lebih banyak contoh mengapa merupakan ide yang baik untuk menangkap Throwable
di tingkat atas dan menghasilkan pesan kesalahan yang berguna.
OutOfMemoryError
Bukan error runtime, tidak ada jaminan bahwa aplikasi dapat memulihkannya. Jika Anda beruntung, Anda mungkin mendapatkan OOM new byte[largeNumber]
tetapi jika alokasi itu tidak cukup untuk menyebabkan OOM, ini dapat dipicu di baris berikutnya atau utas berikutnya. Ini adalah masalah waktu proses karena jika length
input tidak tepercaya, itu harus divalidasi sebelum dipanggil new byte[]
.
NoClassDefFoundError
dapat terjadi di mana saja , karena dipanggil ketika kode java yang dikompilasi tidak dapat menemukan kelas. Jika JDK Anda salah dikonfigurasi, JDK dapat memicu dari mencoba menggunakan java.util.*
kelas dan secara praktis tidak mungkin untuk memprogramnya. Jika Anda secara opsional menyertakan dependensi, Anda harus menggunakan ClassLoader
untuk memeriksa apakah ada, yang melempar ClassNotFoundException
.
ZipError
menunjukkan bahwa file jar yang berisi kelas adalah file zip yang rusak. Ini adalah masalah yang cukup serius dan pada titik ini Anda tidak dapat mempercayai kode apa pun yang dieksekusi dan akan menjadi hal yang tidak bertanggung jawab untuk mencoba "memulihkan" darinya.
java.lang.Error
atau java.lang.Throwable
di tingkat atas dan mencoba melakukan sesuatu dengannya - katakan catat pesan kesalahan. Tetapi pada saat itu tidak ada jaminan bahwa ini akan dilaksanakan. Jika JVM Anda OOM, mencoba untuk mencatat mungkin mengalokasikan lebih banyak String
yang memicu OOM lain.
Dalam lingkungan multithread, Anda paling sering ingin menangkapnya! Saat Anda menangkapnya, catat, dan hentikan seluruh aplikasi! Jika Anda tidak melakukannya, beberapa utas yang mungkin melakukan beberapa bagian penting akan mati, dan sisa aplikasi akan berpikir bahwa semuanya normal. Dari situ, banyak situasi yang tidak diinginkan bisa terjadi. Satu masalah terkecil adalah Anda tidak akan dapat dengan mudah menemukan akar masalah, jika utas lain mulai mengeluarkan beberapa pengecualian karena satu utas tidak berfungsi.
Misalnya, biasanya loop harus:
try {
while (shouldRun()) {
doSomething();
}
}
catch (Throwable t) {
log(t);
stop();
System.exit(1);
}
Bahkan dalam beberapa kasus, Anda ingin menangani Kesalahan yang berbeda secara berbeda, misalnya, pada OutOfMemoryError Anda dapat menutup aplikasi secara teratur (bahkan mungkin membebaskan beberapa memori, dan melanjutkan), pada beberapa lainnya, tidak banyak yang dapat Anda lakukan.
OutOfMemoryError
dan melanjutkan daripada langsung saat itu tidak bijaksana karena program Anda kemudian dalam status tidak ditentukan .
Sebuah Error
biasanya tidak harus dapat ditangkap , karena menunjukkan kondisi normal yang seharusnya tidak terjadi .
Dari Spesifikasi Java API untuk Error
kelas:
An
Error
adalah subclass dariThrowable
yang menunjukkan masalah serius yang seharusnya tidak ditangkap oleh aplikasi yang wajar. Sebagian besar kesalahan tersebut adalah kondisi abnormal. [...]Sebuah metode tidak diharuskan untuk mendeklarasikan dalam klausa lemparannya setiap subkelas Kesalahan yang mungkin terlempar selama pelaksanaan metode tetapi tidak tertangkap, karena kesalahan ini adalah kondisi abnormal yang seharusnya tidak pernah terjadi.
Seperti yang disebutkan dalam spesifikasi, an Error
hanya dilemparkan dalam keadaan yang Kemungkinannya, ketika Error
terjadi, sangat sedikit yang dapat dilakukan aplikasi, dan dalam beberapa keadaan, Java Virtual Machine sendiri mungkin dalam keadaan tidak stabil (seperti VirtualMachineError
)
Meskipun an Error
adalah subclass Throwable
yang artinya dapat ditangkap oleh try-catch
klausa, tetapi mungkin tidak terlalu diperlukan, karena aplikasi akan berada dalam status tidak normal saat Error
dilempar oleh JVM.
Ada juga bagian pendek tentang topik ini dalam Bagian 11.5 Eksepsi Hirarki dari Jawa Bahasa Spesifikasi, 2nd Edition .
Dan ada beberapa kasus lain di mana jika Anda menemukan Kesalahan, Anda harus mengembalikannya . Misalnya ThreadDeath tidak boleh tertangkap, ini dapat menyebabkan masalah besar jika Anda menangkapnya di lingkungan yang terkandung (misalnya server aplikasi):
Aplikasi harus menangkap instance dari kelas ini hanya jika harus dibersihkan setelah dihentikan secara asinkron. Jika ThreadDeath tertangkap oleh suatu metode, penting untuk mencabutnya kembali sehingga utas benar-benar mati.
Error
s.
Sangat, sangat jarang.
Saya melakukannya hanya untuk satu kasus yang diketahui sangat spesifik. Misalnya, java.lang.UnsatisfiedLinkError bisa dilempar jika dua ClassLoader independen memuat DLL yang sama. (Saya setuju bahwa saya harus memindahkan JAR ke classloader bersama)
Tetapi kasus yang paling umum adalah Anda membutuhkan logging untuk mengetahui apa yang terjadi ketika pengguna datang untuk mengeluh. Anda ingin pesan atau popup ke pengguna, daripada mati diam-diam.
Bahkan programmer di C / C ++, mereka memunculkan kesalahan dan memberitahu sesuatu yang tidak dimengerti orang sebelum keluar (misalnya kegagalan memori).
Dalam aplikasi Android saya menangkap java.lang.VerifyError . Perpustakaan yang saya gunakan tidak akan berfungsi di perangkat dengan versi OS lama dan kode perpustakaan akan menimbulkan kesalahan seperti itu. Saya tentu saja dapat menghindari kesalahan dengan memeriksa versi OS saat runtime, tetapi:
Idealnya kami tidak menangani / menangkap kesalahan. Tetapi mungkin ada kasus di mana kita perlu melakukannya, berdasarkan persyaratan kerangka kerja atau aplikasi. Katakanlah saya memiliki daemon XML Parser yang mengimplementasikan DOM Parser yang menghabiskan lebih banyak Memori. Jika ada persyaratan seperti untaian Parser tidak boleh mati ketika mendapat OutOfMemoryError , melainkan harus menanganinya dan mengirim pesan / email ke administrator aplikasi / kerangka kerja.
Ada kesalahan saat JVM tidak lagi berfungsi seperti yang diharapkan, atau hampir. Jika Anda menemukan kesalahan, tidak ada jaminan bahwa blok penangkap akan berjalan, dan bahkan lebih sedikit lagi yang akan berjalan sampai akhir.
Ini juga akan tergantung pada komputer yang sedang berjalan, status memori saat ini, jadi tidak ada cara untuk menguji, mencoba dan melakukan yang terbaik. Anda hanya akan mendapatkan hasil yang sulit.
Anda juga akan menurunkan keterbacaan kode Anda.