Jika suatu objek dalam memori tidak memiliki referensi, itu berarti bahwa objek tidak lagi digunakan, dan itu dapat menjadi kandidat untuk pengumpulan sampah. Namun, karena waktu berjalan dari pengumpul sampah tidak pasti, waktu daur ulang yang sebenarnya dari benda -benda yang dapat dikumpulkan sampah tidak pasti. Untuk suatu objek, selama ada referensi, itu akan selalu ada dalam memori. Jika ada semakin banyak objek seperti ini, melebihi total memori dalam JVM, JVM akan melempar kesalahan outofmemory. Meskipun operasi spesifik pengumpulan sampah dikendalikan oleh JVM, pengembang masih dapat berinteraksi dengan pengumpul sampah sampai batas tertentu, dan tujuannya adalah untuk membantu pengumpul sampah dengan lebih baik mengelola memori aplikasi. Metode interaksi ini adalah menggunakan paket java.lang.ref yang diperkenalkan oleh JDK 1.2.
1 kutipan yang kuat
Kutipan yang kuat adalah kutipan yang paling umum digunakan. Jika suatu objek memiliki referensi yang kuat, pengumpul sampah tidak akan pernah mendaur ulangnya. Ketika ruang memori tidak mencukupi, mesin virtual Java lebih suka melemparkan kesalahan outofmemoryError untuk menyebabkan program mengakhiri secara tidak normal, dan tidak akan mendaur ulang objek dengan referensi yang kuat untuk menyelesaikan masalah memori yang tidak mencukupi.
Misalnya, tanggal = tanggal baru (), tanggal adalah referensi yang kuat untuk suatu objek. Referensi yang kuat untuk objek dapat diteruskan di mana -mana dalam program. Dalam banyak kasus, beberapa referensi akan menunjuk ke objek yang sama secara bersamaan. Keberadaan referensi yang kuat membatasi waktu kelangsungan hidup suatu objek dalam memori. Jika Objek A berisi referensi yang kuat untuk Objek B, maka secara umum, waktu kelangsungan hidup Objek B tidak akan lebih pendek dari objek A. Jika objek A tidak secara eksplisit menetapkan referensi objek B ke nol, hanya setelah objek A adalah sampah yang dikumpulkan akan objek B tidak lagi memiliki referensi yang menunjuk ke sana, dan akan mungkin untuk mendapatkan peluang untuk mendapatkan tempat sampah yang dikumpulkan.
Contoh kode:
paket com.skywang.java; kelas publik StrongReferencetest {public static void main (string [] args) {mydate date = new mydate (); System.gc (); }} Hasil Menjalankan:
<No Output>
Hasilnya menunjukkan bahwa meskipun pengumpulan sampah secara eksplisit disebut, itu adalah referensi yang kuat untuk tanggal, dan tanggal tidak didaur ulang.
Selain referensi yang kuat, paket java.lang.ref menyediakan metode referensi yang berbeda untuk suatu objek. Kolektor sampah JVM memiliki cara berbeda untuk menangani berbagai jenis referensi.
2 kutipan lunak
Jika suatu objek hanya memiliki referensi lunak, ruang memori cukup dan pengumpul sampah tidak akan mendaur ulangnya; Jika ruang memori tidak cukup, memori objek ini akan didaur ulang. Selama pengumpul sampah tidak mendaur ulangnya, objek dapat digunakan oleh program. Referensi lunak dapat digunakan untuk mengimplementasikan cache yang sensitif terhadap memori.
Referensi lunak dapat digunakan bersama dengan antrian referensi (ReferenceQueue). Jika objek yang dirujuk oleh referensi lunak didaur ulang oleh pengumpul sampah, mesin virtual Java akan menambahkan referensi lunak ke antrian referensi terkait.
Referensi lunak lebih lemah daripada referensi kuat dalam kekuatan dan diwakili oleh Softreference. Fungsinya adalah untuk memberi tahu pengumpul sampah mana yang objek dalam program kurang penting dan dapat didaur ulang sementara ketika ada memori yang tidak memadai. Ketika tidak ada memori yang tidak mencukupi dalam JVM, pengumpul sampah akan membebaskan objek yang hanya diarahkan oleh referensi lunak. Jika semua objek ini dilepaskan dan memori tidak cukup, kesalahan outofmemory akan dilemparkan. Referensi lunak sangat ideal untuk membuat cache. Ketika sistem tidak cukup, konten dalam cache dapat dilepaskan. Misalnya, pertimbangkan program editor gambar. Program akan membaca semua konten file gambar ke dalam memori untuk pemrosesan yang mudah. Pengguna juga dapat membuka beberapa file secara bersamaan. Ketika ada terlalu banyak file yang dibuka pada saat yang sama, itu dapat menyebabkan memori yang tidak mencukupi. Jika referensi lunak digunakan untuk menunjuk ke isi file gambar, pengumpul sampah dapat merebut kembali memori ini bila perlu.
Contoh kode:
Paket com.skywang.java; import java.lang.ref.softreference; kelas publik softreferencetest {public static void main (string [] args) {softreference ref = softreference baru (myDate baru ()); ReferenceTest.DrainMemory (); }} Hasil Menjalankan:
<No Output>
Hasil: Ketika memori tidak cukup, referensi lunak diakhiri. Saat referensi lunak dilarang,
Softreference ref = softreference baru (mydate baru ()); Referencetest.drainMemory ();
Setara dengan
Tanggal mydate = mydate baru (); // Terserah JVM untuk menjalankan IF (JVM.Innuficient memory ()) {date = null; System.gc ();} 3 kutipan lemah
Referensi lemah lebih lemah dari referensi lunak dalam kekuatan dan diekspresikan oleh kelas lemah. Tujuannya adalah untuk merujuk pada suatu objek, tetapi tidak mencegah objek dari didaur ulang. Jika referensi yang kuat digunakan, selama referensi ada, objek yang direferensikan tidak dapat didaur ulang. Kutipan yang lemah tidak memiliki masalah ini. Ketika pengumpul sampah berjalan, jika semua referensi ke suatu objek adalah referensi yang lemah, objek akan didaur ulang. Fungsi referensi yang lemah adalah untuk memecahkan hubungan kopling antara objek dalam waktu bertahan hidup yang dibawa oleh referensi yang kuat. Penggunaan referensi lemah yang paling umum adalah di kelas koleksi, terutama di tabel hash. Antarmuka tabel hash memungkinkan objek Java untuk digunakan sebagai kunci. Ketika pasangan nilai kunci dimasukkan ke dalam tabel hash, objek tabel hash itu sendiri memiliki referensi untuk objek kunci dan nilai ini. Jika referensi ini adalah referensi yang kuat, maka selama objek tabel hash itu sendiri masih hidup, objek kunci dan nilai yang terkandung di dalamnya tidak akan didaur ulang. Jika tabel hash dengan waktu bertahan hidup yang panjang berisi banyak pasangan nilai kunci, itu pada akhirnya dapat mengkonsumsi semua memori dalam JVM.
Solusi untuk situasi ini adalah menggunakan referensi yang lemah untuk merujuk objek -objek ini sehingga baik objek kunci dan nilai dalam tabel hash dapat dikumpulkan. Weakhashmap disediakan di Java untuk memenuhi kebutuhan umum ini.
Kode contoh:
Paket com.skywang.java; import java.lang.ref.weakreference; kelas publik lemahan lemahan referenceTest {public static void main (string [] args) {weakreference ref = new loverreference (mydate baru ()); System.gc (); }} Hasil Menjalankan:
OBJ [Tanggal: 1372142034360] adalah GC
Hasil: Ketika pengumpulan sampah JVM berjalan, referensi lemah diakhiri.
Lemah Referensi Ref = Referensi Lemah Baru (myDate baru ()); System.gc ();
Setara dengan:
Date mydate = mydate baru (); // koleksi sampah if (jvm.Innuficient memory ()) {date = null; System.gc ();} Perbedaan antara referensi yang lemah dan referensi lunak adalah bahwa objek dengan hanya referensi lemah memiliki siklus hidup yang lebih pendek. Selama proses utas pengumpul sampah yang memindai area memori di bawah yurisdiksinya, begitu objek dengan hanya referensi lemah ditemukan, ingatannya akan didaur ulang terlepas dari apakah ruang memori saat ini cukup atau tidak. Namun, karena pengumpul sampah adalah utas dengan prioritas yang sangat rendah, itu mungkin tidak selalu ditemukan dengan sangat cepat untuk objek yang hanya memiliki referensi yang lemah.
Referensi yang lemah dapat digunakan bersama dengan antrian referensi (ReferenceQueue). Jika objek yang dirujuk oleh referensi yang lemah adalah sampah yang dikumpulkan, mesin virtual Java akan menambahkan referensi lemah ke antrian referensi terkait.
4 kutipan ilusi
Juga dikenal sebagai Ghost Quotes ~ sebelum memperkenalkan kutipan hantu, pertama -tama kita harus memperkenalkan mekanisme penghentian objek yang disediakan oleh Java. Ada metode finalisasi di kelas objek. Tujuan asli dari desainnya adalah untuk melakukan beberapa pekerjaan pembersihan sebelum objek benar -benar didaur ulang. Karena Java tidak memberikan mekanisme yang mirip dengan C ++ Destructor, itu diimplementasikan melalui metode finalisasi. Tetapi masalahnya adalah bahwa waktu lari pengumpul sampah tidak diperbaiki, sehingga waktu berjalan yang sebenarnya dari pekerjaan pembersihan ini tidak dapat diprediksi. Referensi hantu dapat menyelesaikan masalah ini. Saat membuat phantomreference referensi hantu, Anda harus menentukan antrian referensi. Ketika metode finalisasi suatu objek telah dipanggil, referensi hantu objek akan ditambahkan ke antrian. Dengan memeriksa konten dalam antrian, Anda akan tahu apakah suatu objek siap untuk didaur ulang.
Penggunaan referensi hantu dan antriannya jarang terjadi, dan terutama digunakan untuk mengimplementasikan kontrol penggunaan memori yang relatif bagus, yang sangat bermakna untuk perangkat seluler. Program dapat meminta memori untuk membuat objek baru setelah menentukan bahwa suatu objek harus didaur ulang. Dengan cara ini, memori yang dikonsumsi oleh program dapat dipertahankan pada jumlah yang relatif rendah.
Misalnya, kode berikut memberikan contoh implementasi buffer.
phantombuffer kelas publik {byte private [] data = byte baru [0]; Private ReferenceQueue <byte []> antrian = ReferenceQueue baru <byte []> (); Private Phantomreference <byte []> ref = phantomreference baru <byte []> (data, antrian); byte publik [] get (ukuran int) {if (size <= 0) {lempar baru ilegalargumentException ("ukuran buffer yang salah"); } if (data.length <size) {data = null; System.gc (); // force run the sampah kolektor coba {queue.remove (); // Metode ini akan memblokir sampai antrian tidak kosong. Clear (); // Referensi hantu tidak akan secara otomatis dihapus, Anda harus menjalankan ref = null; data = byte baru [ukuran]; ref = phantomreference baru <byte []> (data, antrian); } catch (InterruptedException e) {E.PrintStackTrace (); }} mengembalikan data; }} Dalam kode di atas, setiap kali buffer baru diterapkan, pertama -tama dipastikan bahwa array byte dari buffer sebelumnya telah berhasil didaur ulang. Metode Hapus yang merujuk pada antrian akan diblokir sampai referensi hantu baru ditambahkan ke antrian. Namun, perlu dicatat bahwa pendekatan ini akan menyebabkan pengumpul sampah dijalankan terlalu berkali -kali, yang dapat menyebabkan program terlalu rendah throughput.
Kode contoh:
Paket com.skywang.java; import java.lang.ref.referencequeUe; impor java.lang.ref.phantomreference; kelas publik phantomreferencetest {public static void main (string [] args) {referensiequeue antreue = new referensiequeue (); Phantomreference ref = phantomreference baru (mydate baru (), antrian); System.gc (); }} Hasil Menjalankan:
OBJ [Tanggal: 1372142282558] adalah GC
Hasilnya menunjukkan bahwa referensi ilusi diakhiri setelah instantiasi.
ReferenceQueue Queue = ReferenceQueue baru (); phantomreference ref = phantomreference baru (mydate baru (), antrian); System.gc ();
Setara dengan:
Tanggal mydate = mydate baru (); tanggal = null;