Catatan: Jika JVM keluar saat kode coba atau tangkap sedang dijalankan, maka blok terakhir mungkin tidak dapat dijalankan. Demikian juga, jika utas yang menjalankan kode coba atau tangkap diinterupsi atau dimatikan, blok terakhir mungkin tidak dijalankan meskipun aplikasi secara keseluruhan berlanjut.
Saya tidak tahu cara lain yang akhirnya blok tidak akan dieksekusi ...
@dhiller - Saya cukup yakin bahwa "power down" disertakan dalam "Jika JVM keluar ..." :-p
Jason Coco
2
@Jason Coco: Menghentikan (karena kehilangan kekuasaan) tidak sama dengan keluar; yang terakhir adalah proses yang kurang lebih terorganisir yang berpuncak pada yang pertama. ; p
pengguna359996
2
AFAIK, jika utas terputus, itu tidak segera dihentikan. Terserah kode di utas untuk mendeteksi gangguan dan menghentikan tugasnya, jadi akhirnya kode harus dijalankan.
Bart van Heukelom
2
Saya rasa jika pengecualian dilemparkan di blok akhirnya, blok lainnya tidak akan dieksekusi.
Menghentikan Java Virtual Machine yang sedang berjalan. Argumen berfungsi sebagai kode status; menurut kesepakatan, kode status bukan nol menunjukkan penghentian abnormal.
Metode ini memanggil exitmetode di kelas Runtime. Metode ini tidak pernah kembali secara normal.
Juga pengecualian harus mematikan Mesin Virtual Java.
kaissun
3
Jika Exception terjadi saat menjalankan System.exit (0), maka akhirnya blok akan dijalankan.
halil
50
Hanya untuk memperluas apa yang orang lain katakan, apa pun yang tidak menyebabkan sesuatu seperti keluarnya JVM akan menyebabkan pemblokiran terakhir. Jadi caranya berikut ini:
ini benar-benar membuatku bingung selama beberapa jam beberapa minggu yang lalu.
nickf
3
Mengembalikan nilai dari blok terakhir dianggap sebagai ide yang buruk. Baik kembali hanya dari blok percobaan, atau kembali dari luar blok percobaan / akhirnya. Kebanyakan IDE akan menandai ini dengan sebuah peringatan.
Ran Biron
1
@nickf Saya rasa Anda tidak lagi bingung. Bisakah Anda menguraikan mekanisme mengapa 1 dikembalikan dan bukan 0. Saya hanya bisa menebak bahwa memori (atau apakah itu register) yang menyimpan nilai kembali dari fungsi yang awalnya memegang 0, ditimpa saat blok akhirnya dieksekusi .
Yaneeve
2
Aneh, di C # tidak diizinkan untuk kembali dari blok terakhir.
JMCF125
3
@RanBiron Tentu saja. Dia sebenarnya tidak merekomendasikan untuk kembali ke dalam blok terakhir, dia hanya mencoba untuk menunjukkan bahwa bahkan pernyataan kembali masih akan menyebabkan kode dalam blok tersebut untuk dieksekusi.
Aquarelle
15
Terkait dengan System.exit, ada juga jenis kegagalan katastropik tertentu di mana blok terakhir tidak dapat dijalankan. Jika JVM kehabisan memori seluruhnya, mungkin JVM keluar begitu saja tanpa tangkapan atau akhirnya terjadi.
Secara khusus, saya ingat sebuah proyek di mana kami dengan bodohnya mencoba menggunakannya
catch(OutOfMemoryError oome){// do stuff}
Ini tidak berhasil karena JVM tidak memiliki memori tersisa untuk mengeksekusi blok catch.
Saat OutOfMemoryError dilempar biasanya ada banyak memori yang tersisa (untuk menghentikan GC meronta-ronta). Namun, jika Anda menangkapnya berulang kali, Anda jelas akan kembali ke GC meronta-ronta.
Tom Hawtin - tackline
Saya pikir seseorang seharusnya tidak menangkap pengecualian yang tidak dicentang!
Sergii Shevchyk
1
Saya mencoba di sisi saya, menggunakan jdk7, tetapi itu menangkap Kesalahan OutOfMemory!
Jaskey
10
try{for(;;);}finally{System.err.println("?");}
Dalam hal ini, akhirnya tidak akan dijalankan (kecuali deprecated Thread.stopdipanggil, atau yang setara, katakanlah, melalui antarmuka alat).
Saya tidak berpikir ada tangkapan. Mungkin di sana Anda membayangkan tangkapan yang tidak ada. Jika kita masukkan secara eksplisit throw, maka finallyblok tersebut akan dieksekusi seperti yang diharapkan. try { throw new ThreadDeath(); } finally { System.err.println("?"); }
Tom Hawtin - tackline
9
Tutorial Sun salah dikutip di sini di utas ini.
Catatan: Jika JVM keluar saat kode coba atau tangkap sedang dijalankan, maka blok terakhir tidak akan dijalankan. Demikian juga, jika thread yang menjalankan kode coba atau tangkap diinterupsi atau dimatikan, blok terakhir tidak akan dijalankan meskipun aplikasi secara keseluruhan berlanjut.
Jika Anda melihat tutorial sun lebih dekat untuk akhirnya memblokir, itu tidak mengatakan "tidak akan mengeksekusi" tetapi "mungkin tidak mengeksekusi" Berikut adalah deskripsi yang benar
Catatan: Jika JVM keluar saat kode coba atau tangkap sedang dijalankan, maka blok terakhir mungkin tidak dapat dijalankan. Demikian juga, jika utas yang menjalankan kode coba atau tangkap diinterupsi atau dimatikan, blok terakhir mungkin tidak dijalankan meskipun aplikasi secara keseluruhan berlanjut.
Alasan yang jelas untuk perilaku ini adalah, panggilan ke system.exit () diproses dalam thread sistem runtime yang mungkin memerlukan waktu untuk mematikan jvm, sementara penjadwal thread akhirnya dapat meminta untuk dieksekusi. Jadi akhirnya dirancang untuk selalu mengeksekusi, tetapi jika Anda mematikan jvm, mungkin saja jvm dimatikan sebelum akhirnya dieksekusi.
Secara teknis, blok percobaan tidak pernah keluar sehingga blok terakhir seharusnya tidak pernah mendapat kesempatan untuk dieksekusi. Hal yang sama dapat dikatakan untuk putaran tak terbatas.
Jeff Mercado
6
Jika JVM keluar saat kode coba atau tangkap sedang dijalankan, maka blok terakhir tidak dapat dijalankan. ( sumber )
Normal Shutdown - ini terjadi baik ketika utas non-daemon terakhir keluar ATAU ketika Runtime.exit () ( sumber )
Ketika sebuah thread keluar, JVM melakukan inventarisasi thread yang sedang berjalan, dan jika satu-satunya thread yang tersisa adalah thread daemon, JVM memulai penghentian secara tertib. Saat JVM berhenti, setiap utas daemon yang tersisa ditinggalkan akhirnya blok tidak dieksekusi, tumpukan tidak dibatalkan, JVM baru saja keluar. Untaian daemon harus digunakan dengan hemat, beberapa aktivitas pemrosesan dapat ditinggalkan dengan aman kapan saja tanpa pembersihan. Secara khusus, berbahaya menggunakan utas daemon untuk tugas-tugas yang mungkin melakukan segala jenis I / O. Untaian daemon paling baik disimpan untuk tugas "rumah tangga", seperti utas latar belakang yang secara berkala menghapus entri kadaluwarsa dari cache dalam memori. ( sumber )
Contoh keluar utas non-daemon terakhir:
publicclassTestDaemon{privatestaticRunnable runnable =newRunnable(){@Overridepublicvoid run(){try{while(true){System.out.println("Is alive");Thread.sleep(10);// throw new RuntimeException();}}catch(Throwable t){
t.printStackTrace();}finally{System.out.println("This will never be executed.");}}};publicstaticvoid main(String[] args)throwsInterruptedException{Thread daemon =newThread(runnable);
daemon.setDaemon(true);
daemon.start();Thread.sleep(100);// daemon.stop();System.out.println("Last non-daemon thread exits.");}}
Keluaran:
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Last non-daemon thread exits.Is alive
Is alive
Is alive
Is alive
Is alive
Ada dua cara untuk menghentikan eksekusi kode blok:
1. Gunakan System.exit ();
2. Jika entah bagaimana kendali eksekusi tidak mencapai blok percobaan.
Lihat:
publicclassMain{publicstaticvoid main (String[]args){if(true){System.out.println("will exceute");}else{try{System.out.println("result = "+5/0);}catch(ArithmeticException e){System.out.println("will not exceute");}finally{System.out.println("will not exceute");}}}}
Saya telah menemukan kasus yang sangat spesifik dari blok terakhir yang tidak mengeksekusi terkait secara khusus dengan kerangka bermain.
Saya terkejut menemukan bahwa blok terakhir dalam kode aksi pengontrol ini hanya dipanggil setelah Pengecualian, tetapi tidak pernah ketika panggilan benar-benar berhasil.
try{InputStream is = getInputStreamMethod();
renderBinary(is,"out.zip");catch(Exception e){
e.printStackTrace();}finally{
cleanUp();}
Mungkin utas dihentikan atau sesuatu ketika renderBinary () dipanggil. Saya akan curiga hal yang sama terjadi untuk panggilan render () lainnya, tetapi saya tidak memverifikasinya.
Saya memecahkan masalah dengan memindahkan renderBinary () ke setelah coba / tangkap. Penyelidikan lebih lanjut mengungkapkan bahwa play menyediakan anotasi @Finally untuk membuat metode yang dijalankan setelah tindakan pengontrol dijalankan. Peringatan di sini adalah bahwa ini akan dipanggil setelah eksekusi tindakan APA PUN di pengontrol, jadi ini mungkin tidak selalu menjadi pilihan yang baik.
//If ArithmeticException Occur Inner finally would not be executedclassTemp{publicstaticvoid main(String[] s){try{int x =10/s.length;System.out.println(x);try{int z[]=newint[s.length];
z[10]=1000;}catch(ArrayIndexOutOfBoundsException e){System.out.println(e);}finally{System.out.println("Inner finally");}}catch(ArithmeticException e){System.out.println(e);}finally{System.out.println("Outer Finally");}System.out.println("Remaining Code");}}
Jawaban:
dari Sun Tutorials
Saya tidak tahu cara lain yang akhirnya blok tidak akan dieksekusi ...
sumber
System.exit mematikan Mesin Virtual.
"bye" tidak dicetak dalam kode di atas.
sumber
Hanya untuk memperluas apa yang orang lain katakan, apa pun yang tidak menyebabkan sesuatu seperti keluarnya JVM akan menyebabkan pemblokiran terakhir. Jadi caranya berikut ini:
anehnya akan mengkompilasi dan mengembalikan 1.
sumber
Terkait dengan System.exit, ada juga jenis kegagalan katastropik tertentu di mana blok terakhir tidak dapat dijalankan. Jika JVM kehabisan memori seluruhnya, mungkin JVM keluar begitu saja tanpa tangkapan atau akhirnya terjadi.
Secara khusus, saya ingat sebuah proyek di mana kami dengan bodohnya mencoba menggunakannya
Ini tidak berhasil karena JVM tidak memiliki memori tersisa untuk mengeksekusi blok catch.
sumber
Dalam hal ini, akhirnya tidak akan dijalankan (kecuali deprecated
Thread.stop
dipanggil, atau yang setara, katakanlah, melalui antarmuka alat).sumber
throw
, makafinally
blok tersebut akan dieksekusi seperti yang diharapkan.try { throw new ThreadDeath(); } finally { System.err.println("?"); }
Tutorial Sun salah dikutip di sini di utas ini.
Catatan: Jika JVM keluar saat kode coba atau tangkap sedang dijalankan, maka blok terakhir tidak akan dijalankan. Demikian juga, jika thread yang menjalankan kode coba atau tangkap diinterupsi atau dimatikan, blok terakhir tidak akan dijalankan meskipun aplikasi secara keseluruhan berlanjut.
Jika Anda melihat tutorial sun lebih dekat untuk akhirnya memblokir, itu tidak mengatakan "tidak akan mengeksekusi" tetapi "mungkin tidak mengeksekusi" Berikut adalah deskripsi yang benar
Alasan yang jelas untuk perilaku ini adalah, panggilan ke system.exit () diproses dalam thread sistem runtime yang mungkin memerlukan waktu untuk mematikan jvm, sementara penjadwal thread akhirnya dapat meminta untuk dieksekusi. Jadi akhirnya dirancang untuk selalu mengeksekusi, tetapi jika Anda mematikan jvm, mungkin saja jvm dimatikan sebelum akhirnya dieksekusi.
sumber
Juga jika terjadi deadlock / livelock di dalam
try
blok.Inilah kode yang mendemonstrasikannya:
Kode ini menghasilkan keluaran sebagai berikut:
dan "akhirnya" tidak pernah dicetak
sumber
Jika JVM keluar saat kode coba atau tangkap sedang dijalankan, maka blok terakhir tidak dapat dijalankan. ( sumber )
Normal Shutdown - ini terjadi baik ketika utas non-daemon terakhir keluar ATAU ketika Runtime.exit () ( sumber )
Ketika sebuah thread keluar, JVM melakukan inventarisasi thread yang sedang berjalan, dan jika satu-satunya thread yang tersisa adalah thread daemon, JVM memulai penghentian secara tertib. Saat JVM berhenti, setiap utas daemon yang tersisa ditinggalkan akhirnya blok tidak dieksekusi, tumpukan tidak dibatalkan, JVM baru saja keluar. Untaian daemon harus digunakan dengan hemat, beberapa aktivitas pemrosesan dapat ditinggalkan dengan aman kapan saja tanpa pembersihan. Secara khusus, berbahaya menggunakan utas daemon untuk tugas-tugas yang mungkin melakukan segala jenis I / O. Untaian daemon paling baik disimpan untuk tugas "rumah tangga", seperti utas latar belakang yang secara berkala menghapus entri kadaluwarsa dari cache dalam memori. ( sumber )
Contoh keluar utas non-daemon terakhir:
Keluaran:
sumber
Dalam kasus berikut, akhirnya blok tidak akan dijalankan: -
System.exit(0)
dipanggil daritry
blok.try
blok AndaMungkin juga ada kasus pinggiran lainnya, di mana blokir akhirnya tidak akan dieksekusi.
sumber
Ada dua cara untuk menghentikan eksekusi kode blok:
1. Gunakan System.exit ();
2. Jika entah bagaimana kendali eksekusi tidak mencapai blok percobaan.
Lihat:
sumber
Saya telah menemukan kasus yang sangat spesifik dari blok terakhir yang tidak mengeksekusi terkait secara khusus dengan kerangka bermain.
Saya terkejut menemukan bahwa blok terakhir dalam kode aksi pengontrol ini hanya dipanggil setelah Pengecualian, tetapi tidak pernah ketika panggilan benar-benar berhasil.
Mungkin utas dihentikan atau sesuatu ketika renderBinary () dipanggil. Saya akan curiga hal yang sama terjadi untuk panggilan render () lainnya, tetapi saya tidak memverifikasinya.
Saya memecahkan masalah dengan memindahkan renderBinary () ke setelah coba / tangkap. Penyelidikan lebih lanjut mengungkapkan bahwa play menyediakan anotasi @Finally untuk membuat metode yang dijalankan setelah tindakan pengontrol dijalankan. Peringatan di sini adalah bahwa ini akan dipanggil setelah eksekusi tindakan APA PUN di pengontrol, jadi ini mungkin tidak selalu menjadi pilihan yang baik.
sumber
sumber