Kata kunci akhirnya di Java biasanya digunakan dengan blok Coba Cobe. Digunakan untuk melakukan beberapa operasi rilis sumber daya sebelum akhir metode atau ketika pengecualian terjadi. Baru -baru ini saya juga telah melihat beberapa artikel di internet yang membahas urutan eksekusi kata kunci TREE Catch akhirnya, dan diberikan bahwa blok akhirnya dieksekusi di akhir metode.
Pandangan ini umumnya percaya bahwa:
1) Kata kunci akhirnya dieksekusi sebelum kembali ke metode sebelumnya setelah pernyataan pengembalian program. Nilai pengembalian akan disimpan di area sementara. Setelah blok terakhir dieksekusi, nilai area sementara akan dikembalikan.
2) Jika ada nilai pengembalian di blok akhirnya, itu akan menggantikan nilai yang disimpan di area sementara dari blok percobaan atau tangkapan sebelumnya dalam program.
Tapi apakah masalahnya benar -benar seperti ini? Mari kita pikirkan dengan cermat. JVM menjelaskan dan menjalankan instruksi bytecode saat runtime. Ketika itu mengeksekusi pernyataan pengembalian, dia tidak tahu apakah akhirnya ada blok sesudahnya? Bagaimana jika tidak ada blok akhirnya? Apakah itu instruksi bytecode atau instruksi komputer harus jelas. JVM tidak terlalu pintar. Instruksi yang sama harus jelas dan tidak akan mengandung dua makna. Oleh karena itu, tidak peduli apa pernyataan pengembalian saat berjalan, konten tumpukan akan muncul dan dikembalikan ke metode panggilan.
Pada saat yang sama, kita dapat melihat bahwa buku "Deep Into Java Virtual Machine" memberikan penjelasan lain. Ketika kompiler Java mengkompilasi klausa akhirnya, instruksi JSR akan dihasilkan. Ini menyebabkan JVM dipanggil ke subrutin mini untuk dieksekusi, yaitu, pada akhirnya blok. Pada saat yang sama, pernyataan Return 0 dalam program disusun ke dalam variabel pengembalian di tumpukan ke variabel lokal sebelum memanggil instruksi JSR, dan instruksi JSR dipanggil, blok akhirnya dieksekusi, dan blok akhirnya kembali. Ketika nilai pengembalian dalam variabel lokal didorong ke tumpukan, instruksi IRETURN dieksekusi, nilai pengembalian muncul dari tumpukan, dan kembali ke metode panggilan. Di sini, nilai pengembalian disimpan dalam variabel lokal sebelum menjalankan instruksi JSR, karena pengecualian dapat terjadi selama pelaksanaan blok akhirnya atau ada juga nilai pengembalian. Hanya dengan cara ini, konsistensi eksekusi program akhir dapat dipastikan. Sejak "DeDedening Java Virtual Machine" telah ditulis selama beberapa waktu, implementasi dan versi kompiler JVM yang digunakan oleh penulis juga berbeda dari yang dibahas dalam artikel ini. Jadi setelah pengujian, ada sedikit perbedaan dalam generasi bytecode untuk berbagai implementasi kompiler atau versi kompiler yang berbeda untuk program yang sama. Jika Anda tertarik, Anda dapat melihat bytecode yang dihasilkan oleh klausa akhirnya dalam buku ini.
Generasi bytecode dalam artikel ini disusun dan dihasilkan oleh versi kompiler JDK8U-25 Oracle.
Mari kita lihat contoh di bawah ini.
1. Coba tangkap akhirnya:
kelas publik akhirnya {public static void main (string [] args) {int r = test (); System.out.println (r); } public static int test () {coba {System.out.println ("coba"); // kembalikan 1/0; kembali 0; } catch (Exception e) {System.out.println ("Exception"); mengembalikan 100; } akhirnya {System.out.println ("akhirnya"); }}}Gunakan pernyataan Return 0 di blok coba, dan hasil yang berjalan dari program adalah:
mencoba
Akhirnya
0
Gunakan pernyataan pengembalian 1/0 di blok coba, dan hasil dari program yang berjalan adalah:
Pengecualian
Akhirnya
100
Bahkan, melalui hasil berjalan, kita dapat melihat bahwa blok akhirnya dieksekusi setelah pernyataan lain sebelum pernyataan pengembalian di blok TREE atau Catch. Dengan kata lain, urutan penulisan program tidak sesuai dengan urutan eksekusi kami, karena JVM menafsirkan dan menjalankan bytecode, jadi kami perlu melihat bagaimana kompiler Java mengkompilasi kode ini dan melihat seperti apa bentuk bytecode.
2. Bagian dari bytecode yang dihasilkan oleh program: (Silakan merujuk ke instruksi Java Bytecode)
tes int statis publik (); deskriptor: () I Flags: ACC_PUBLIC, ACC_STATIC Kode: Stack = 2, penduduk setempat = 2, args_size = 0 0: getStatic #20 // bidang java/lang/system.out: ljava/io/printstream; 3: LDC #36 // String Coba 5: Invokevirtual #38 // Metode java/io/printStream.println: (ljava/lang/string;) v 8: getstatic #20 // field java/lang/system.out: ljava/io/printStream; 11: LDC #41 // String Akhirnya 13: Invokevirtual #38 // Metode Java/io/printStream.println: (ljava/lang/string;) V 16: ICONTS_0 17: IRETURN 18: STORE_0 19: GetStatic #20 // Field Java/Lang/System. 22: LDC #43 // String Exception 24: Invokevirtual #38 // Metode java/io/printStream.println: (ljava/lang/string;) v 27: getStatic #20 // field java/lang/system.out: ljava/io/printStream; 30: LDC #41 // String Akhirnya 32: Invokevirtual #38 // Metode Java/io/printStream.println: (ljava/lang/string;) V 35: Bipush 100 37: Ireturn 38: Store_1 39: GetStatic #20 // Field Java/Lang/Lang/Lang. 42: LDC #41 // String Akhirnya 44: Invokevirtual #38 // Metode Java/io/printStream.println: (ljava/lang/string;) v 47: aload_1 48: ATHROW TABLE: Dari ke Target Tipe 0 8 18 Kelas Java/Lang/Pengecualian 0 8 38
Dari bagian merah, kita dapat melihat bahwa baris 10 dan 11 sesuai dengan instruksi pernyataan blok akhirnya, 16 dan 17 sesuai dengan pengembalian 0 instruksi, setelah pernyataan lain pada blok coba, sebelum kembali. 19 dan 20 sesuai dengan instruksi blok akhirnya, 21 dan 22 sesuai dengan instruksi pengembalian 100 pernyataan. Setelah menangkap pernyataan lain dan sebelum kembali, kita dapat melihat bahwa semuanya terjadi di balik ini adalah bahwa kompiler Java telah melakukan semua ini untuk kita. Adapun pengecualian yang terjadi dalam program, JVM akan menemukan lokasi alamat yang sesuai untuk menangani pengecualian dari tabel pengecualian untuk dieksekusi.
Oleh karena itu kita dapat menyimpulkan bahwa pernyataan di blok akhirnya akan dimasukkan oleh kompiler Java sebelum pernyataan try block and catch block return, dan setelah pernyataan lainnya. Tidak ada subrutin untuk menghasilkan panggilan JSR di sini. Itu sebabnya, apakah itu melaksanakan blok mencoba atau mengeksekusi blok tangkapan, blok akhirnya akan dieksekusi sebelum metode kembali.
Analisis komprehensif di atas dari waktu eksekusi Java akhirnya blok adalah semua konten yang saya bagikan dengan Anda. Saya harap Anda dapat memberi Anda referensi dan saya harap Anda dapat mendukung wulin.com lebih lanjut.