Kutipan FinalReference
Kelas ini adalah jenis paket, menunjukkan bahwa itu bukan bagian publik dan mewarisi dari referensi, yang berarti bahwa itu juga merupakan jenis referensi tertentu. Oleh karena itu, sebelum setiap objek yang dibungkus di dalamnya didaur ulang, itu akan ditempatkan di ReferqyebCequeue yang ditentukan.
Objek referensi ini secara khusus digunakan untuk kelas dengan metode finalisasi. Dapat dipahami bahwa setiap objek dengan metode yang sesuai akan dienkapsulasi sebagai objek FinalRefernece.
Karena metode finalisasi ditentukan oleh objek, implementasinya yang default kosong. Maka jika metode ini ditulis ulang, badan metode pasti tidak akan kosong. Perbedaan ini dapat dilakukan melalui ini. Selama metode finalisasi mengimplementasikan kelas yang tidak kosong, objek yang dihasilkan perlu didaftarkan di FinalRefernece.
Langkah ini dapat didaftarkan sesuai dengan memanggil metode konstruktor default objek selama newinstance.
Metode Daftar Finalzer#
Ketika metode ini dipanggil terutama, objek finalizer yang sesuai akan dihasilkan, dan objek finakis diwarisi dari finalReference. Metode ini dinyatakan sebagai berikut:
/ * Dipanggil oleh VM */Static Void Register (Object Finalizee) {New Finalizer (finalizee);} Seperti yang dapat dilihat dari komentar di atas, metode ini akan dipanggil oleh JVM pada periode tertentu.
Kemudian beralih ke konstruktor finakisasi, seperti yang ditunjukkan di bawah ini:
finalizer pribadi (Object Finalizee) {super (finalizee, antrian); menambahkan();} Dapat dilihat bahwa objek referensi yang sesuai akan dipanggil kembali melalui antrian. Fungsi ADD adalah untuk menyimpan semua objek yang belum menyelesaikan metode dan memanggilnya di akhir System.shutdown . Atur melalui Runtime#runFinalizersOnExit .
ReferenceQueue
Antrian referensi ini akan ditempatkan dalam antrian ini sebelum objek internal dari objek referensi yang sesuai didaur ulang (deskripsi terperinci akan dijelaskan dalam artikel lain tentang referensi.), Karena hanya objek yang sesuai yang perlu diperoleh dari antrian ini, maka objek ini pasti siap untuk didaur ulang.
Kemudian hubungi metode finalisasi yang sesuai sebelum daur ulang.
FinalzerThread Thread
Utas ini terus mendapatkan data dari antrian, dan kemudian memanggil metode finalisasi yang sesuai. Kode yang sesuai adalah sebagai berikut:
untuk (;;) {coba {finalizer f = (finalizer) queue.remove (); f.runfinalizer (JLA); } catch (InterruptedException x) {// abaikan dan lanjutkan}}Runfinalizer yang sesuai adalah sebagai berikut:
disinkronkan (ini) {if (hasbeenfinalized ()) kembali; hapus ();} coba {objek finalize = this.get (); if (finalizee! = null &&! (Finalizee instance dari java.lang.enum)) {jla.invokefinalize (finalizee); / * Slot tumpukan bening yang berisi variabel ini, untuk mengurangi kemungkinan retensi palsu dengan GC */ finalizee yang konservatif = null; }} catch (Throwable x) {} super.clear ();Dalam logika di atas, panggilan pertama hapus dan hapus dari finalisasi. Metode ini adalah untuk memastikan bahwa finalisasi setiap objek hanya akan dipanggil paling banyak sekali, yaitu, panggilan saat ini selesai. Ini akan dicatat dalam keadaan yang sesuai, yaitu, Hasbeenalized Returns True (pada kenyataannya, itu berarti mengarahkan pointer berikutnya ke dalamnya sendiri. Yaitu, itu tidak pernah diselesaikan, dan tidak perlu memanggil finalisasi lagi).
Berikutnya adalah memanggil metode finalisasi yang sesuai. jla.invokeFinalize di atas sebenarnya untuk memanggil metode finalisasi dari objek yang sesuai. Dalam proses ini, objek asli pertama kali diperoleh melalui GET. Di seluruh proses JVM, referensi tidak diatur ke null sebelum mendaur ulang untuk finizereference. Karena di sini, objek referensi yang sesuai selalu dapat diperoleh.
Setelah diproses, Clear yang sesuai akhirnya dipanggil untuk menghapus referensi yang sesuai. Ini mencapai efek referensi akhir tidak memiliki objek lain untuk referensi.
Dalam pemrosesan di atas, tidak ada batasan waktu untuk memanggil finalisasi. Oleh karena itu, setelah finalisasi suatu objek disebut secara perlahan, itu akan mempengaruhi eksekusi seluruh rantai daur ulang, dan pengecualian OOM yang sesuai akan dihasilkan. Oleh karena itu, kecuali dalam kasus khusus, jangan menulis ulang finalisasi. Harus ada metode lain untuk menangani skenario yang sesuai. Misalnya, finalizableReference di jambu.
Finalisasi memulai utas
Di utas di atas, itu akan dimulai selama startup proses yang sesuai. Dapat dipahami bahwa objek memicu inisialisasi kelas finalizer dengan memanggil register(object) . Kemudian, di blok inisialisasi statis, utas daur ulang yang sesuai akan dimulai. Kode inisialisasi yang sesuai adalah sebagai berikut:
static {threadGroup tg = thread.currentThread (). getThreadGroup (); untuk (threadgroup tgn = tg; tgn! = null; tg = tgn, tgn = tg.getParent ()); Thread finalzer = finalzerThread baru (TG); finalizer.setPriority (thread.max_priority - 2); finalizer.setdaemon (true); finalizer.start ();}Statis di atas adalah blok inisialisasi statis, yaitu, selama finalizer kelas digunakan, panggilan yang sesuai akan dipicu. Grup utas yang digunakan di sini adalah grup utas sistem, dan prioritasnya masih relatif tinggi, dan dikonfigurasi sebagai utas latar belakang.
Saat menggunakan JStack untuk mencetak utas, utas yang ditunjukkan di bawah gambar yang muncul dimulai di sini. Seperti yang ditunjukkan pada gambar di bawah ini
Meringkaskan
Seluruh finalisasi bekerja bersama melalui FinalReference oleh JVM dan kelas Java yang sesuai. Tidak semua diimplementasikan oleh JVM, sehingga dapat dipertimbangkan bahwa itu tidak terlalu mendasarinya, tetapi untuk mengimplementasikan semantik yang sesuai. Semuanya dilakukan oleh Java normal dan dioperasikan oleh JVM. Memahami seluruh proses juga merupakan pemahaman tentang mekanisme berjalan Java itu sendiri.