Apakah ada kondisi dimana akhirnya tidak bisa berjalan di java? Terima kasih.
Apakah ada kondisi dimana akhirnya tidak bisa berjalan di java? Terima kasih.
Jawaban:
dari Sun Tutorials
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 ...
System.exit mematikan Mesin Virtual.
Menghentikan Java Virtual Machine yang sedang berjalan. Argumen berfungsi sebagai kode status; menurut kesepakatan, kode status bukan nol menunjukkan penghentian abnormal.
Metode ini memanggil
exit
metode di kelasRuntime
. Metode ini tidak pernah kembali secara normal.
try {
System.out.println("hello");
System.exit(0);
}
finally {
System.out.println("bye");
} // try-finally
"bye" tidak dicetak dalam kode di atas.
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:
public static int Stupid() {
try {
return 0;
}
finally {
return 1;
}
}
anehnya akan mengkompilasi dan mengembalikan 1.
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.
try { for (;;); } finally { System.err.println("?"); }
Dalam hal ini, akhirnya tidak akan dijalankan (kecuali deprecated Thread.stop
dipanggil, atau yang setara, katakanlah, melalui antarmuka alat).
throw
, maka finally
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
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.
Juga jika terjadi deadlock / livelock di dalam try
blok.
Inilah kode yang mendemonstrasikannya:
public class DeadLocker {
private static class SampleRunnable implements Runnable {
private String threadId;
private Object lock1;
private Object lock2;
public SampleRunnable(String threadId, Object lock1, Object lock2) {
super();
this.threadId = threadId;
this.lock1 = lock1;
this.lock2 = lock2;
}
@Override
public void run() {
try {
synchronized (lock1) {
System.out.println(threadId + " inside lock1");
Thread.sleep(1000);
synchronized (lock2) {
System.out.println(threadId + " inside lock2");
}
}
} catch (Exception e) {
} finally {
System.out.println("finally");
}
}
}
public static void main(String[] args) throws Exception {
Object ob1 = new Object();
Object ob2 = new Object();
Thread t1 = new Thread(new SampleRunnable("t1", ob1, ob2));
Thread t2 = new Thread(new SampleRunnable("t2", ob2, ob1));
t1.start();
t2.start();
}
}
Kode ini menghasilkan keluaran sebagai berikut:
t1 inside lock1
t2 inside lock1
dan "akhirnya" tidak pernah dicetak
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:
public class TestDaemon {
private static Runnable runnable = new Runnable() {
@Override
public void 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.");
}
}
};
public static void main(String[] args) throws InterruptedException {
Thread daemon = new Thread(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
Dalam kasus berikut, akhirnya blok tidak akan dijalankan: -
System.exit(0)
dipanggil dari try
blok. try
blok AndaMungkin juga ada kasus pinggiran lainnya, di mana blokir akhirnya tidak akan dieksekusi.
Ada dua cara untuk menghentikan eksekusi kode blok:
1. Gunakan System.exit ();
2. Jika entah bagaimana kendali eksekusi tidak mencapai blok percobaan.
Lihat:
public class Main
{
public static void 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 executed
class Temp
{
public static void main(String[] s)
{
try
{
int x = 10/s.length;
System.out.println(x);
try
{
int z[] = new int[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");
}
}