Java: perbedaan antara referensi kuat / lunak / lemah / hantu

178

Saya telah membaca artikel ini tentang topik tersebut, tetapi saya tidak begitu memahaminya. Tolong beri saya beberapa saran bersama dengan contoh ketika menjelaskan konsep.

Matthias Braun
sumber
4
Saya sudah membaca dokumen itu, tidak membantu saya membayangkan apa bedanya. (mungkin karena ini adalah dokumen yang sulit dibaca)
14
Jika Anda membaca artikel itu dan masih tidak mengerti, apakah Anda memiliki pertanyaan khusus tentangnya? Sulit untuk menjawab "tolong jelaskan Foo kepada saya," "inilah artinya," "Saya tidak mengerti" tanpa spesifik tentang bagian mana yang tidak Anda dapatkan.
yshavit
@LouisWasserman Tautan teratas tidak lagi valid.
Mehraj Malik

Jawaban:

142

Java menyediakan dua jenis / kelas Objek Referensi : kuat dan lemah . Obyek Referensi yang Lemah dapat dibagi lagi menjadi lunak dan hantu .

  • Kuat
  • Lemah
    • lembut
    • hantu

Mari kita selangkah demi selangkah.

Obyek Referensi Kuat

StringBuilder builder = new StringBuilder();

Ini adalah tipe / kelas default dari Object Reference, jika tidak ditentukan secara berbeda: builderadalah Object Reference yang kuat. Referensi semacam ini membuat objek yang dirujuk tidak memenuhi syarat untuk GC. Yaitu, setiap kali sebuah objek direferensikan oleh rantai Objek Referensi yang kuat , itu tidak bisa menjadi sampah yang dikumpulkan.

Obyek Referensi Lemah

WeakReference<StringBuilder> weakBuilder = new WeakReference<StringBuilder>(builder);

Objek Referensi Lemah bukan tipe / kelas default dari Objek Referensi dan untuk digunakan mereka harus secara eksplisit ditentukan seperti pada contoh di atas. Referensi semacam ini membuat objek referensi memenuhi syarat untuk GC. Artinya, jika satu-satunya referensi yang dapat dijangkau untuk StringBuilderobjek dalam memori, sebenarnya, adalah referensi yang lemah, maka GC diizinkan untuk mengumpulkan sampah StringBuilderobjek. Ketika suatu objek dalam memori hanya dapat dijangkau oleh Objek Referensi Lemah, objek tersebut secara otomatis memenuhi syarat untuk GC.

Tingkat Kelemahan

Dua tingkat kelemahan yang berbeda dapat dimasukkan: lunak dan hantu .

Sebuah lembut Obyek Referensi pada dasarnya adalah Object Reference lemah yang tetap dalam memori sedikit lebih: biasanya, menolak siklus GC sampai tidak ada memori yang tersedia dan ada risiko OutOfMemoryError(dalam hal ini, dapat dihapus).

Di sisi lain, Obyek Referensi hantu hanya berguna untuk mengetahui dengan tepat kapan suatu objek telah dihapus secara efektif dari memori: biasanya mereka digunakan untuk memperbaiki perilaku penyelesaian / kebangkitan yang aneh , karena mereka sebenarnya tidak mengembalikan objek itu sendiri tetapi hanya membantu melacak keberadaan ingatan mereka .

Objek Referensi Lemah sangat ideal untuk mengimplementasikan modul cache. Bahkan, semacam penggusuran otomatis dapat diimplementasikan dengan memungkinkan GC untuk membersihkan area memori setiap kali objek / nilai tidak lagi dapat dijangkau oleh rantai referensi yang kuat. Contohnya adalah WeakHashMap yang mempertahankan kunci lemah.

Paolo Maresca
sumber
76

Referensi yang lemah:

Referensi yang lemah, sederhananya, adalah referensi yang tidak cukup kuat untuk memaksa objek untuk tetap berada dalam memori. Referensi yang lemah memungkinkan Anda memanfaatkan kemampuan pengumpul sampah untuk menentukan jangkauan Anda, sehingga Anda tidak harus melakukannya sendiri.

Referensi Lembut:

Referensi lunak persis seperti referensi lemah, kecuali bahwa ia kurang bersemangat untuk membuang objek yang dirujuk. Objek yang hanya dapat dijangkau dengan lemah (referensi terkuat untuk itu adalah Referensi Lemah) akan dibuang pada siklus pengumpulan sampah berikutnya, tetapi objek yang dapat dijangkau dengan lembut umumnya akan bertahan untuk sementara waktu.

Referensi Phantom:

Referensi hantu sangat berbeda dari SoftReference atau WeakReference. Cengkeramannya pada objek sangat lemah sehingga Anda bahkan tidak dapat mengambil objek - metode get () selalu mengembalikan null. Satu-satunya penggunaan untuk referensi semacam itu adalah melacak ketika itu akan enqueued menjadi ReferenceQueue, karena pada titik itu Anda tahu objek yang ditunjuknya sudah mati.

Teks ini diekstraksi dari: https://weblogs.java.net/blog/2006/05/04/understanding-weak-references

Punith Raj
sumber
1
Sementara segala sesuatu dalam jawaban ini terlihat benar, bagi saya sepertinya ada kesalahan pada halaman web yang ditautkan. The Javadoc untuk paket java.lang.ref dan bahwa untuk PhantomReference menunjukkan bahwa sebuah objek tidak sampah yang dikumpulkan sampai setelah itu tidak lagi "hantu terjangkau", menyiratkan bahwa (tidak seperti SoftReference) PhantomReference suatu harus dequeued sebelum objek itu mengacu kaleng dikumpulkan sampah ... dan enqueued tidak menunjukkan bahwa memori yang terkait telah dibebaskan.
Theodore Murdock
2
Sebagai catatan, saya lebih suka tinggal di dunia di mana posting blog itu benar.
Theodore Murdock
1
@TheodoreMurdock javadoc sudah benar. Referensi hantu tidak menghalangi pengumpulan sampah sama sekali. Setelah sebuah objek di enqueued, itu tidak dapat disimpan bahkan oleh finalizer, karena finalizers sudah berjalan. Sudah mati, tapi belum pergi.
Leliel
@Leliel Sebenarnya, referensi hantu tidak pada kenyataannya pengumpulan menghamhat sampah setelah itu enqueued ... saya menyadari ini baru-baru ini ketika bug disebabkan thread pembersihan untuk keluar awal. Keberadaan referensi hantu cukup untuk memastikan bahwa setiap objek referensi hantu tetap di tumpukan saya, tidak tersedia untuk koleksi ... jika Anda gagal memproses antrian, atau gagal membuat referensi hantu memenuhi syarat untuk gc saat memproses antrian ( dan jangan menghapus () referensi hantu), maka kebocoran memori Anda akan mencakup referensi hantu dan objek yang direferensikan.
Theodore Murdock
25

Perbedaan sederhana antara SoftReferencedan WeakReferencedisediakan oleh Pengembang Android .

Perbedaan antara a SoftReferencedan a WeakReferenceadalah titik waktu di mana keputusan dibuat untuk menghapus dan membuat rujukan referensi:

  • A SoftReferenceharus dibersihkan dan enqueued selambat mungkin, yaitu, jika VM dalam bahaya kehabisan memori.

  • A WeakReferencedapat dihapus dan enqueued segera setelah diketahui memiliki referensi lemah.

Muhammad Nabeel Arif
sumber
16

Tiga istilah yang telah Anda gunakan sebagian besar terkait dengan kelayakan Objek untuk mengumpulkan sampah.

Referensi Lemah :: Ini adalah referensi yang tidak cukup kuat untuk memaksa objek tetap berada di memori. Ini adalah pengumpul sampah yang ingin mengumpulkan benda itu untuk pengumpulan sampah. Anda tidak dapat memaksa GC untuk tidak mengambilnya .

Referensi Lembut :: Ini kurang lebih sama seperti referensi lemah. Tetapi Anda dapat mengatakan bahwa itu memegang objek sedikit lebih kuat daripada referensi lemah dari pengumpulan sampah.

Jika pengumpul sampah mengumpulkan referensi lemah dalam siklus kehidupan pertama itu sendiri, ia akan mengumpulkan referensi lunak dalam siklus pengumpulan sampah berikutnya.

Referensi Kuat :: Ini bertolak belakang dengan dua jenis referensi di atas. Mereka kurang suka mengumpulkan sampah (Kebanyakan mereka tidak pernah dikumpulkan.)

Anda dapat merujuk ke tautan berikut untuk info lebih lanjut:

http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/ref/Reference.html

Sabya
sumber
3
Saya pikir ini salah - "Jika pengumpul Sampah mengumpulkan referensi lemah dalam siklus kehidupan pertama itu sendiri, itu akan mengumpulkan referensi lunak dalam siklus berikutnya pengumpulan Sampah." Tidak harus seperti itu, bagaimana Anda bisa begitu yakin bahwa mereka terjadi dalam menjalankan GC berturut-turut? GC dapat memungkinkan objek yang direferensikan lunak untuk hidup bahkan dalam menjalankan ke-2 dan ke-3 juga. Tidak ada dokumentasi untuk itu, jika ada maka tolong sebutkan tautan yang menentukan.
Saurabh Patil
2
Juga, jawaban Anda sedikit kabur, lihat kalimat ini 'Kurang lebih sama dengan referensi lemah. Tetapi Anda dapat mengatakan bahwa benda itu memegang objek sedikit lebih kuat daripada referensi lemah dari pengumpulan sampah. ' - dia jelas bertanya tentang perbedaan dan bukan kesamaan, semua kata-kata ini menambah lebih banyak kebingungan daripada kejelasan topik.
Saurabh Patil
@SaurabhPatil - Merindukan komentar Anda. Ini dia jawabannya. 1. "dia jelas bertanya tentang perbedaan dan bukan kesamaan" - Lihat deskripsi pertanyaan (bukan "hanya judul") "Tolong beri saya beberapa saran, dan tolong beri saya beberapa contoh untuk menggambarkan". 2. "Tetapi Anda dapat mengatakan bahwa itu menahan objek sedikit lebih ...." Saya pikir SOF memberikan opsi untuk memilih dan memberikan jawaban baru juga.
Sabya
14

Artikel ini bisa sangat membantu untuk memahami referensi yang kuat, lembut, lemah dan phantom.


Untuk memberi Anda ringkasan,

Jika Anda memiliki referensi yang kuat ke suatu objek, maka objek tersebut tidak pernah dapat dikumpulkan / direklamasi oleh GC (Pengumpul Sampah).

Jika Anda hanya memiliki referensi lemah ke objek (tanpa referensi kuat), maka objek tersebut akan direklamasi oleh GC dalam siklus GC berikutnya.

Jika Anda hanya memiliki referensi lunak ke suatu objek (tanpa referensi kuat), maka objek tersebut akan direklamasi oleh GC hanya ketika JVM kehabisan memori.

Kami membuat referensi hantu ke objek untuk melacak ketika objek enqueued ke dalam ReferenceQueue. Setelah Anda tahu bahwa Anda dapat melakukan finalisasi berbutir halus. (Ini akan menyelamatkan Anda dari secara tidak sengaja menghidupkan kembali objek karena referensi hantu tidak memberi Anda referensi). Saya sarankan Anda membaca artikel ini untuk mendapatkan detail mendalam tentang ini.


Jadi Anda dapat mengatakan bahwa, referensi yang kuat memiliki kekuatan tertinggi (tidak pernah dapat dikumpulkan oleh GC)

Referensi lunak lebih kuat daripada referensi yang lemah (karena mereka dapat keluar dari siklus GC sampai JVM kehabisan memori)

Referensi yang lemah bahkan kurang kuat daripada referensi lunak (karena mereka tidak dapat lepas dari siklus GC dan akan direklamasi jika objek tidak memiliki referensi kuat lainnya).


Analogi Restoran

  • Pelayan - GC
  • Anda - Obyek di tumpukan
  • Area restoran / ruang - Heap space
  • Pelanggan Baru - Objek baru yang ingin meja di restoran

Sekarang jika Anda adalah pelanggan yang kuat (analog dengan referensi kuat), maka bahkan jika pelanggan baru datang di restoran atau apa yang pernah terjadi, Anda tidak akan pernah meninggalkan meja Anda (area memori di tumpukan). Pelayan tidak berhak untuk memberitahu Anda (atau bahkan meminta Anda) untuk meninggalkan restoran.

Jika Anda adalah pelanggan lunak (analog dengan referensi lembut), maka jika pelanggan baru datang di restoran, pelayan tidak akan meminta Anda untuk meninggalkan meja kecuali tidak ada meja kosong yang tersisa untuk mengakomodasi pelanggan baru. (Dengan kata lain pelayan akan meminta Anda untuk meninggalkan meja hanya jika pelanggan baru masuk dan tidak ada meja lain yang tersisa untuk pelanggan baru ini)

Jika Anda adalah pelanggan yang lemah (analog dengan referensi lemah), maka pelayan, atas kehendaknya, dapat (kapan saja) meminta Anda untuk meninggalkan restoran: P

Kothari yang mewah
sumber
10

4 derajat referensi - Strong, Weak, Soft, Phantom

Kuat - adalah semacam referensi, yang membuat objek yang direferensikan tidak memenuhi syarat untuk GC. kelas pembangun. misalnya - StringBuilder

Lemah - adalah referensi yang memenuhi syarat untuk GC.

Soft - adalah jenis referensi yang objeknya memenuhi syarat untuk GC sampai memori tersedia. Terbaik untuk cache gambar. Ini akan menahan mereka sampai memori tersedia.

Phantom - adalah sejenis referensi yang objeknya secara langsung memenuhi syarat untuk GC. Digunakan hanya untuk mengetahui kapan suatu objek dihapus dari memori.

menggunakan:

  1. Memungkinkan Anda mengidentifikasi kapan suatu objek dikeluarkan dengan benar dari memori.

  2. ketika finalize()metode kelebihan beban, maka GC mungkin tidak terjadi secara tepat waktu untuk objek yang memenuhi syarat GC dari dua kelas. Jadi referensi hantu membuat mereka memenuhi syarat untuk GC sebelumnyafinalize() , itulah sebabnya Anda bisa mendapatkan OutOfMemoryErrors bahkan ketika sebagian besar tumpukan adalah sampah.

Referensi yang lemah ideal untuk mengimplementasikan modul cache.

Preetham RU
sumber
10

Referensi yang kuat

Ini adalah referensi objek reguler Anda yang kami kode setiap hari:

Employee emp = new Employee();

Variabel "emp" memegang referensi kuat ke objek Karyawan dan objek yang dapat dijangkau melalui rantai referensi kuat apa pun tidak memenuhi syarat untuk pengumpulan sampah. Biasanya, ini yang Anda inginkan tetapi tidak selalu. Sekarang anggaplah kita mengambil banyak karyawan dari database dalam koleksi atau peta, dan kita perlu melakukan banyak pemrosesan pada mereka secara teratur, Jadi untuk menjaga kinerja, kita akan menyimpannya dalam cache.

Sejauh ini bagus tetapi sekarang kami membutuhkan data yang berbeda dan kami tidak membutuhkan objek Karyawan tersebut dan ini tidak dirujuk dari mana pun kecuali cache. Yang menyebabkan kebocoran memori karena benda-benda ini tidak digunakan tetapi masih belum memenuhi syarat untuk pengumpulan sampah dan kami tidak dapat menghapus objek-objek dari cache karena kami tidak memiliki referensi untuk itu? Jadi di sini kita perlu mengosongkan seluruh cache secara manual yang membosankan atau kita bisa menggunakan referensi jenis lain misalnya Referensi Lemah.

Referensi yang lemah

Referensi yang lemah tidak menyematkan objek ke memori dan akan GC di siklus GC berikutnya jika tidak dirujuk dari referensi lain. Kita bisa menggunakan kelas WeakReference yang disediakan oleh Java untuk membuat jenis cache di atas, yang tidak akan menyimpan objek yang tidak dirujuk dari tempat lain.

WeakReference<Cache> cache = new WeakReference<Cache>(data);

Untuk mengakses data, Anda perlu memanggil cache.get (). Panggilan untuk mendapatkan ini dapat mengembalikan nol jika referensi lemah adalah sampah yang dikumpulkan: Anda harus memeriksa nilai yang dikembalikan untuk menghindari NPE. Java menyediakan koleksi yang menggunakan referensi lemah misalnya, kelas WeakHashMap menyimpan kunci (bukan nilai) sebagai referensi lemah. Jika kuncinya adalah GC, maka nilai tersebut akan secara otomatis dihapus dari peta juga.

Karena referensi yang lemah adalah objek juga kita perlu cara untuk membersihkannya (mereka tidak lagi berguna ketika objek yang mereka rujuk telah GC'd). Jika Anda meneruskan ReferenceQueue ke dalam konstruktor untuk referensi yang lemah maka pemulung akan menambahkan referensi yang lemah ke ReferenceQueue sebelum mereka selesai atau GC. Anda dapat secara berkala memproses antrian ini dan menangani referensi mati.

Referensi Lembut

SoftReference seperti WeakReference tetapi kecil kemungkinannya sampah yang dikumpulkan. Referensi lunak dihapus atas kebijakan pengumpul sampah dalam menanggapi permintaan memori. Mesin virtual menjamin bahwa semua referensi lunak untuk objek yang dapat dijangkau dengan lembut akan telah dihapus sebelum pernah membuang OutOfMemoryError.

Referensi Phantom

Referensi Phantom adalah yang terlemah dari semua jenis referensi, memanggil get on mereka akan selalu mengembalikan nol. Objek direferensikan phantomly setelah selesai, tetapi sebelum memori yang dialokasikan telah direklamasi, Berbeda dengan referensi lemah yang enqueued sebelum mereka selesai atau GC'd referensi Phantom jarang digunakan.

Jadi, bagaimana manfaatnya? Saat Anda membuat referensi hantu Anda harus selalu memberikan ReferensiQueue. Ini menunjukkan bahwa Anda dapat menggunakan referensi hantu untuk melihat kapan objek Anda GC.

Hei, jadi jika referensi lemah enqueued ketika mereka dianggap selesai tetapi belum GC kita bisa membuat referensi kuat baru ke objek di blok finalizer dan mencegah objek menjadi GC. Yap, Anda bisa tetapi Anda mungkin tidak seharusnya melakukan ini. Untuk memeriksa kasus ini, siklus GC akan terjadi setidaknya dua kali untuk setiap objek kecuali objek itu hanya dapat dijangkau oleh referensi hantu. Inilah sebabnya mengapa Anda dapat kehabisan tumpukan bahkan ketika memori Anda mengandung banyak sampah. Referensi hantu dapat mencegah hal ini.

Anda dapat membaca lebih lanjut di artikel saya Jenis Referensi di Jawa (Strong, Soft, Weak, Phantom) .

Naresh Joshi
sumber
Anda menulis bahwa refrences yang lemah akan menjadi GC'ed di siklus berikutnya jika tidak direfrensikan dari refrences lain ... tetapi seharusnya tidak terjadi hal yang sama dengan stron refrences? jika stron refrence tidak diakses dengan cara apa pun maka akan dihapus ... lalu jika demikian maka di mana bedanya lagi ...? #confused
filemonczyk
1
Jika suatu objek dirujuk dari katakanlah s1 (kuat) dan s2 (kuat), objek tidak akan memenuhi syarat untuk pengumpulan sampah sampai kedua s1 dan s2 direferensikan tetapi jika objek tersebut direferensikan dari s1 (lemah) dan s2 ( kuat) maka objek akan memenuhi syarat untuk pengumpulan sampah dalam siklus GC berikutnya ketika mendapat dereferensi dari s2 saja, karena s1 adalah referensi yang lemah dan jika objek tidak memiliki referensi lain kecuali yang lemah itu memenuhi syarat untuk GC
Naresh Joshi