Ketika program menciptakan entitas tipe referensi seperti objek, array, dll., Sistem akan mengalokasikan sepotong memori untuk objek dalam memori heap, dan objek disimpan dalam bagian memori ini. Ketika bagian memori ini tidak lagi dirujuk oleh variabel referensi apa pun, bagian memori menjadi sampah, menunggu mekanisme pengumpulan sampah didaur ulang. Mekanisme pengumpulan sampah memiliki tiga karakteristik:
Mekanisme pengumpulan sampah hanya bertanggung jawab untuk mendaur ulang objek dalam memori heap, dan tidak akan mendaur ulang sumber daya fisik apa pun (seperti koneksi basis data, sumber daya file terbuka, dll.), Juga tidak akan mendaur ulang memori yang dialokasikan ke objek dengan cara selain cara membuat objek, (seperti memori yang diterapkan oleh objek panggilan malloc dengan metode lokal)
Program ini tidak dapat secara akurat mengontrol pengoperasian pengumpulan sampah, sehingga hanya dapat direkomendasikan untuk pengumpulan sampah. Ada dua metode yang disarankan: System.gc () dan runtime.getRuntime (). GC ()
Sebelum pengumpulan sampah, metode finalisasi () akan selalu disebut terlebih dahulu, tetapi sama dengan waktu pengumpulan sampah, dan metode finak finalisasi () juga tidak yakin.
Mengenai tiga karakteristik di atas, ada tiga masalah:
1. Pekerjaan pembersihan harus dilakukan secara manual untuk membebaskan memori dan sumber daya fisik lainnya yang dialokasikan dengan cara selain cara membuat objek. Dan berhati -hatilah untuk menghilangkan referensi objek yang kadaluwarsa, jika tidak, OOM dapat disebabkan.
Pembersihan manual biasanya menggunakan struktur kode seperti mencoba ... akhirnya ...
Contohnya adalah sebagai berikut:
Impor java.io.fileInputStream; import java.io.filenotfoundException; import java.io.ioException; Public Class ManualClear {public static void main (string [] args) {FileInputStream FileinputStream = null; coba {fileInputStream = new fileInputStream ("./ src/manualclear.java"); } catch (FileNotFoundException e) {System.out.println (e.getMessage ()); e.printstacktrace (); kembali; } coba {byte [] bbuf = byte baru [1024]; int hasread = 0; coba {while ((hasread = fileInputStream.read (bbuf))> 0) {System.out.println (string baru (bbuf, 0, hasread)); }} catch (ioException e) {E.PrintStackTrace (); }} akhirnya {coba {fileInputStream.close (); } catch (ioException e) {e.printstacktrace (); }}}}Biasanya ada tiga kasus OOM umum yang disebabkan oleh referensi ke objek yang kedaluwarsa. Ketiga kasus ini biasanya tidak mudah dideteksi, dan tidak akan ada masalah dalam waktu singkat. Namun, setelah waktu yang lama, jumlah objek yang bocor pada akhirnya akan menyebabkan program macet.
Ketika kelas mengelola memori dengan sendirinya, Anda harus mewaspadai kebocoran memori sebagai berikut:
Impor java.util.arrays; import java.util.empttackException; kelas stack {private objek [] elemen; ukuran int pribadi; private static final int default_inital_capacity = 16; public stack () {elements = objek baru [default_inital_capacity]; } public void push (objek e) {ensureCapacity (); elemen [ukuran ++] = e; } public object pop () {if (size == 0) {lempar new dossttackException (); } return elemen [-size]; } private void ensureCapacity () {if (elements.length == size) {elemen = arrays.copyof (elemen, 2 * ukuran + 1); }}} kelas publik stackdemo {public static void main (string [] args) {stack stack = new stack (); untuk (int i = 0; i <10000; i ++) {stack.push (objek baru ()); } untuk (int i = 0; i <10000; i ++) {stack.pop (); }}}Alasan kebocoran memori adalah bahwa bahkan jika objek lain pada tumpukan tidak lagi dirujuk, elemen [] array di kelas tumpukan masih memegang referensi ke objek -objek ini, yang mengakibatkan objek yang tidak didaur ulang dengan pengumpulan sampah. Oleh karena itu, ketika kelas perlu mengelola memori dengan sendirinya, waspadalah apakah referensi kadaluwarsa yang dikelola oleh secara internal didereferal dalam waktu. Dalam contoh ini, hanya setelah tumpukan dirilis, yang ditampilkan akan ditampilkan.
elemen [ukuran] = null;
Cache harus waspada terhadap kebocoran memori. Situasi ini biasanya terjadi bahwa begitu objek dimasukkan ke dalam cache, kemungkinan mudah untuk dilupakan jika tidak digunakan untuk waktu yang lama. Biasanya, WakehashMap dapat digunakan untuk mewakili cache. Setelah item dalam cache berakhir, mereka dapat dihapus secara otomatis. Atau dapat dieksekusi secara berkala dengan utas latar belakang untuk menghapus item kadaluwarsa dalam buffer.
Pendaftaran pendengar atau panggilan balik paling baik ditampilkan untuk dibatalkan.
2. Jangan sebut finalisasi () secara manual, itu dipanggil ke pengumpul sampah
3. Hindari menggunakan metode finalisasi () kecuali digunakan sebagai menilai kondisi akhir untuk menemukan bahwa objek belum dibersihkan dengan benar; Ini digunakan sebagai jaringan keamanan untuk membersihkan sumber daya sistem ketika secara manual membersihkan panggilan lupa. Pembersihan yang tertunda tidak boleh dibersihkan. Jika Anda mencatat informasi tentang sumber daya pembersihan yang terlupakan pada saat yang sama, juga nyaman untuk kesalahan ditemukan nanti dan memodifikasi kode pembersihan yang terlupakan tepat waktu; Bebaskan sumber daya sistem kritis yang tidak terlalu sangat diperoleh dengan metode lokal di objek.
Karena metode finalisasi () tidak dipastikan secara akurat, yang terbaik adalah tidak melepaskan sumber daya utama, tetapi dapat digunakan dalam tiga kasus yang disebutkan di atas. Kasus pertama adalah sebagai berikut:
Buku kelas {boolean checkout = false; buku publik (checkout boolean) {this.checkout = checkout; } public void checkIn () {checkout = false; } @Override Protected void finalize () melempar Throwable {if (checkout) {System.out.println ("Kesalahan: periksa"); }}} kelas publik finumezeCheckObjectuse {public static void main (string [] args) {buku baru (true); System.gc (); }}Hasil Eksekusi:
Kesalahan: Lihat
Objek buku dalam contoh harus dalam keadaan checkin sebelum dirilis, jika tidak tidak dapat dirilis. Implementasi dalam finalisasi dapat membantu menemukan objek ilegal dalam waktu, atau lebih langsung, menggunakan variabel referensi untuk secara langsung merujuknya dalam finalisasi, sehingga dapat masuk kembali ke keadaan dapat dijangkau, dan kemudian memprosesnya lagi.
Poin lain yang perlu diperhatikan adalah bahwa jika subclass mengesampingkan metode finalisasi kelas induk, tetapi lupa untuk secara manual memanggil super. Finalize atau proses finalisasi subclass memiliki pengecualian, menghasilkan super. Finalisasi tidak dieksekusi, maka metode akhir dari kelas induk tidak akan pernah dipanggil.
sebagai berikut:
class Parent {@Override Protected void finalize () melempar Throwable {System.out.println (getClass (). getName () + "finalize start"); }} class son memperluas induk {@Override void finalize () lemparan lempar {system.out.println (getSclass (). getName () + "finalize start"); }} kelas publik superfinalizelost {public static void main (string [] args) {new son (); System.gc (); }}Hasil Menjalankan:
Son Finalize Start
atau
class Parent {@Override Protected void finalize () melempar Throwable {System.out.println (getClass (). getName () + "finalize start"); }} class son memperluas induk {@Override void finalize () lemparan lempar {system.out.println (getSclass (). getName () + "finalize start"); int i = 5 /0; super.finalisasi (); }} kelas publik superfinalizelost {public static void main (string [] args) {new son (); System.gc (); }}Hasil Eksekusi:
Son Finalize Start
Untuk kasus kedua, Anda dapat menggunakan struktur coba ... akhirnya ... untuk menyelesaikannya, tetapi untuk kasus pertama, lebih baik menggunakan metode yang disebut Metode Akhir Guardian. Contohnya adalah sebagai berikut
class Parent2 {Private Final Object FinalizeGuardian = Objek baru () {Protected void finalize () melempar lempar {System.out.println ("Jalankan logika dalam metode penghentian kelas induk di sini"); }; };} class son2 memperluas Parent2 {@Override Protected void finalize () melempar lempar {System.out.println (getSclass (). getName () + "finalisasi start"); int i = 5 /0; super.finalisasi (); }} kelas public finalizeGuardian {public static void main (string [] args) {new son2 (); System.gc (); }}Hasil Eksekusi:
Jalankan logika dalam metode terminasi kelas induk di sini
Son2 Finalisasi Mulai
Ini memastikan bahwa operasi yang diperlukan dalam metode akhir kelas induk dijalankan.
Di atas adalah semua tentang artikel ini, saya harap ini akan membantu untuk pembelajaran semua orang.