Ada 4 jenis referensi di Java: StrongReference, SoftReference, WeakReference dan PhantomReference (referensi hantu legendaris haha),
Keempat jenis referensi ini berkaitan erat dengan GC. Mari kita lihat definisi dan skenario penggunaannya satu per satu:
1. Referensi Kuat
StrongReference adalah implementasi referensi default Java. Ini akan bertahan di JVM selama mungkin. Jika tidak ada objek yang menunjuk ke sana, maka akan didaur ulang setelah eksekusi GC.
kode Jawa
Copy kode kodenya sebagai berikut:
@Tes
public void strongReference() {
Referensi objek = Objek baru();
/**
* Buat StrongReference melalui tugas
*/
Objek strongReference = referensi;
menegaskanSame(referensi, Referensi kuat);
referensi = nol;
Sistem.gc();
/**
* StrongReference tidak akan didaur ulang setelah GC
*/
menegaskanNotNull(Referensi kuat);
}
2. Referensi Lemah & Peta Hash Lemah
WeakReference, seperti namanya, adalah referensi lemah. Ketika objek yang direferensikan tidak lagi memiliki referensi kuat di JVM, referensi lemah akan otomatis didaur ulang setelah GC.
Copy kode kodenya sebagai berikut:
@Tes
public void lemahReferensi() {
Referensi objek = Objek baru();
WeakReference<Objek>weakRerference = WeakReference<Objek>(referensi);
menegaskanSame(referensi, lemahRerference.get());
referensi = nol;
Sistem.gc();
/**
* Jika tidak ada referensi kuat yang menunjuk ke referensi, referensi lemah akan otomatis didaur ulang setelah GC
*/
menegaskanNull(weakRerference.get());
}
WeakHashMap menggunakan WeakReference sebagai kunci. Setelah tidak ada referensi kuat ke kunci tersebut, WeakHashMap akan secara otomatis menghapus entri yang relevan setelah GC.
Copy kode kodenya sebagai berikut:
@Tes
public void lemahHashMap() melempar InterruptedException {
Peta<Objek, Objek>weakHashMap = new WeakHashMap<Objek, Objek>();
Kunci objek = Objek baru();
Nilai objek = Objek baru();
lemahHashMap.put(kunci, nilai);
menegaskanTrue(weakHashMap.containsValue(nilai));
kunci = nol;
Sistem.gc();
/**
* Tunggu entri yang tidak valid untuk masuk keReferenceQueue sehingga entri tersebut dapat dihapus saat getTable dipanggil lagi
*/
Thread.tidur(1000);
/**
* Setelah tidak ada referensi kuat ke kunci tersebut, WeakHashMap akan secara otomatis menghapus entri yang relevan setelah GC
*/
menegaskanFalse(weakHashMap.containsValue(nilai));
}
3.Referensi Lunak
SoftReference pada dasarnya memiliki karakteristik yang sama dengan WeakReference. Perbedaan terbesarnya adalah SoftReference akan menyimpan referensi selama mungkin hingga JVM kehabisan memori sebelum didaur ulang (jaminan mesin virtual).
Copy kode kodenya sebagai berikut:
@Tes
kekosongan publik softReference() {
Referensi objek = Objek baru();
SoftReference<Object> softRerference = SoftReference<Object>(referensi);
menegaskanNotNull(softRerference.get());
referensi = nol;
Sistem.gc();
/**
* referensi lunak hanya akan didaur ulang sebelum jvm OutOfMemory, sehingga sangat cocok untuk aplikasi caching
*/
menegaskanNotNull(softRerference.get());
}
4. Referensi Phantom
Sebagai protagonis artikel ini, Referensi Phantom sangat berbeda dari WeakReference dan SoftReference, karena metode get()-nya selalu mengembalikan null, dari situlah namanya berasal.
kode Jawa
Copy kode kodenya sebagai berikut:
@Tes
kekosongan publik phantomReferenceAlwaysNull() {
Referensi objek = Objek baru();
PhantomReference<Object> phantomReference = PhantomReference<Object> baru(referensi, ReferentQueue<Object>());
/**
* Metode get referensi phantom selalu mengembalikan null
*/
menegaskanNull(phantomReference.get());
}
Anda mungkin bertanya, apa gunanya referensi yang selalu mengembalikan null? Harap perhatikan parameter keduaReferenceQueue saat membuat PhantomReference (sebenarnya, WeakReference & SoftReference juga dapat memiliki parameter ini).
Satu-satunya kegunaan PhantomReference adalah untuk melacak kapan referensi dimasukkan ke dalam ReferentQueue.
5. Antrean Relevansi
Ketika WeakReference mulai mengembalikan null, objek yang ditunjuknya siap untuk didaur ulang. Pada saat ini, beberapa pekerjaan pembersihan yang sesuai dapat dilakukan. Berikan ReferrenceQueue ke konstruktor Referensi akan secara otomatis Objek dimasukkan ke dalam ReferenQueue. WeakHashMap menggunakan ReferensiQueue untuk menghapus entri yang kuncinya tidak lagi memiliki referensi yang kuat.
kode Jawa
Copy kode kodenya sebagai berikut:
@Tes
public void referenceQueue() melempar InterruptedException {
Referensi objek = Objek baru();
Antrian Referensi<Objek> referenceQueue = Antrean Referensi baru<Objek>();
WeakReference<Objek>weakReference = WeakReference<Objek>(referensi, referenceQueue);
menegaskanFalse(weakReference.isEnqueued());
Referensi<? extends Obyek> yang disurvei = referenceQueue.poll();
menegaskanNull(disurvei);
referensi = nol;
Sistem.gc();
menegaskanTrue(weakReference.isEnqueued());
Referensi<? extends Object> dihapus = referenceQueue.remove();
menegaskanNotNull(dihapus);
}
6. Referensi Phantom vs Referensi Lemah
PhantomReference memiliki dua manfaat. Pertama, memungkinkan kita mengetahui secara pasti kapan objek dihapus dari memori. Fitur ini dapat digunakan untuk beberapa kebutuhan khusus (seperti Distributed GC, XWork dan google-guice juga menggunakan PhantomReference Melakukan beberapa pekerjaan pembersihan).
Kedua, ini dapat menghindari beberapa masalah mendasar yang disebabkan oleh finalisasi. Seperti disebutkan di atas, satu-satunya fungsi PhantomReference adalah melacak kapan referensi dimasukkan ke dalam ReferentQueue, tetapi WeakReference juga memiliki fungsi yang sesuai.
Ini tentang metode finalisasi dari Object. Metode ini akan dipanggil sebelum gc dijalankan. Jika suatu objek membebani metode finalisasi secara berlebihan dan dengan sengaja membuat referensi yang kuat ke dirinya sendiri di dalam metode tersebut, hal ini akan menyebabkan putaran GC ini tidak dapat dilakukan. didaur ulang. Objek ini dapat menyebabkan GC apa pun. Hasil akhirnya adalah ada banyak Sampah di JVM tetapi OutOfMemory. Masalah ini dapat dihindari dengan menggunakan PhantomReference, karena PhantomReference sedang dalam tahap finalisasi Ini didaur ulang setelah metode dijalankan, yang berarti saat ini tidak mungkin mendapatkan referensi asli, sehingga masalah di atas tidak akan terjadi. Tentu saja, ini adalah contoh yang sangat ekstrim dan umumnya tidak terjadi.
7. Perbandingan
Referensi Lembut vs Lemah vs Phantom | ||||
---|---|---|---|---|
Jenis | Tujuan | Menggunakan | Ketika GCed | Kelas Pelaksana |
Referensi Kuat | Referensi biasa Menjaga objek tetap hidup selama direferensikan. | referensi biasa. | Objek apa pun yang tidak ditunjuk dapat direklamasi. | bawaan |
Referensi Lembut | Menjaga objek tetap hidup asalkan ada cukup memori. | untuk menjaga objek tetap hidup bahkan setelah klien menghapus referensi mereka (cache yang sensitif terhadap memori), jika klien mulai memintanya lagi berdasarkan kunci. | Setelah gc pass pertama, JVM memutuskan masih perlu mendapatkan kembali lebih banyak ruang. | java.lang.ref.SoftReference |
Referensi Lemah | Menjaga objek tetap hidup hanya saat sedang digunakan (dapat dijangkau) oleh klien. | Wadah yang secara otomatis menghapus objek yang tidak digunakan lagi. | Setelah gc menentukan objek tersebut hanya dapat dijangkau dengan lemah | java.lang.ref.WeakReference java.util.WeakHashMap |
Referensi Hantu | Memungkinkan Anda membersihkan setelah finalisasi tetapi sebelum ruang diambil kembali (menggantikan atau menambah penggunaan finalisasi()) | Pemrosesan pembersihan khusus | Setelah finalisasi. | java.lang.ref.PhantomReference |
8. Ringkasan
Aplikasi umum tidak akan melibatkan pemrograman Referensi, tetapi memahami pengetahuan ini akan membantu dalam memahami prinsip kerja GC dan penyetelan kinerja. Mungkin juga digunakan saat mengimplementasikan beberapa fasilitas dasar seperti caching.