Sebuah referensi yang lemah , hanya menempatkan, adalah referensi yang tidak cukup kuat untuk memaksa sebuah objek untuk tetap dalam memori. Referensi yang lemah memungkinkan Anda memanfaatkan kemampuan pengumpul sampah untuk menentukan jangkauan Anda, sehingga Anda tidak harus melakukannya sendiri. Anda membuat referensi yang lemah seperti ini:
dan kemudian di tempat lain dalam kode yang dapat Anda gunakan
weakWidget.get()untuk mendapatkan yang sebenarnya
Widget objek yang . Tentu saja referensi yang lemah tidak cukup kuat untuk mencegah pengumpulan sampah, jadi Anda mungkin menemukan (jika tidak ada referensi kuat untuk widget) yang weakWidget.get()tiba -
tiba mulai kembali null.
...
Referensi lunak
Sebuah referensi yang lembut persis seperti referensi yang lemah, kecuali bahwa itu kurang bersemangat untuk membuang objek yang mengacu. Objek yang hanya bisa dijangkau dengan lemah (referensi terkuat untuk itu)WeakReferences ) akan dibuang pada siklus pengumpulan sampah berikutnya, tetapi sebuah objek yang dapat dijangkau secara perlahan umumnya akan bertahan untuk sementara waktu.
SoftReferencestidak diharuskan untuk berperilaku berbeda dari itu
WeakReferences, tetapi dalam praktiknya objek yang dapat dijangkau dengan lembut umumnya dipertahankan selama ingatan masih banyak. Ini menjadikannya fondasi yang bagus untuk cache, seperti cache gambar yang dijelaskan di atas, karena Anda dapat membiarkan pengumpul sampah khawatir tentang seberapa terjangkau objek tersebut (objek yang sangat dapat dijangkau tidak akan pernah dihapus dari cache) dan seberapa parahnya membutuhkan memori yang mereka konsumsi.
Dan Peter Kessler menambahkan dalam komentar:
Sun JRE memperlakukan SoftReferences secara berbeda dari WeakReferences. Kami berupaya mempertahankan objek yang dirujuk oleh SoftReference jika tidak ada tekanan pada memori yang tersedia. Satu detail: kebijakan untuk JRE "-client" dan "-server" berbeda: JRE -client mencoba untuk menjaga jejak Anda kecil dengan memilih untuk menghapus SoftReferences daripada memperluas heap, sedangkan -server JRE mencoba untuk menjaga Anda kinerja tinggi dengan lebih suka memperluas heap (jika mungkin) daripada menghapus SoftReferences. Satu ukuran tidak cocok untuk semua.
Posting tidak tersedia lagi, Anda dapat menemukannya di mesin wayback
riccardo.tasso
kali ini, arsip tidak lagi tersedia
user1506104
209
Referensi yang lemah dikumpulkan dengan penuh semangat. Jika GC menemukan bahwa suatu objek dapat dijangkau dengan lemah (dapat dicapai hanya melalui referensi yang lemah), itu akan menghapus referensi yang lemah ke objek itu dengan segera. Dengan demikian, mereka baik untuk menyimpan referensi ke objek yang juga disimpan oleh program Anda (sangat direferensikan) "informasi terkait", seperti informasi refleksi yang di-cache tentang kelas, atau pembungkus untuk objek, dll. Apa pun yang membuat tidak masuk akal untuk menjaga setelah objek itu dikaitkan dengan GC-ed. Ketika referensi yang lemah dihapus, itu akan enqueued dalam antrian referensi bahwa jajak pendapat kode Anda di suatu tempat, dan itu membuang objek terkait juga. Artinya, Anda menyimpan informasi tambahan tentang suatu objek, tetapi informasi itu tidak diperlukan begitu objek yang dirujuknya pergi. Sebenarnya, dalam situasi tertentu Anda bahkan dapat subkelas WeakReference dan menyimpan informasi tambahan terkait tentang objek di bidang subkelas WeakReference. Penggunaan WeakReference yang khas lainnya adalah bersama dengan Maps untuk menjaga instance kanonik.
SoftReferences di sisi lain baik untuk menyimpan sumber daya eksternal yang dapat diolah kembali karena GC biasanya menunda untuk menghapusnya. Namun dijamin bahwa semua SoftReferences akan dihapus sebelum OutOfMemoryError dilempar, sehingga secara teoritis mereka tidak dapat menyebabkan OOME [*].
Contoh kasus penggunaan umum adalah menyimpan bentuk konten yang diurai dari file. Anda akan menerapkan sistem tempat Anda memuat file, menguraikannya, dan menyimpan SoftReference ke objek root dari representasi yang diuraikan. Lain kali Anda membutuhkan file, Anda akan mencoba mengambilnya melalui SoftReference. Jika Anda dapat mengambilnya, Anda membebaskan diri dari beban / parse lain, dan jika GC menghapusnya sementara itu, Anda memuatnya kembali. Dengan begitu, Anda menggunakan memori bebas untuk pengoptimalan kinerja, tetapi jangan mengambil risiko OOME.
Sekarang untuk [*]. Menyimpan SoftReference tidak dapat menyebabkan OOME sendiri. Jika di sisi lain Anda secara keliru menggunakan SoftReference untuk suatu tugas, sebuah WeakReference dimaksudkan untuk digunakan (yaitu, Anda menyimpan informasi yang terkait dengan Objek yang entah bagaimana sangat dirujuk, dan membuangnya ketika objek Referensi dihapus), Anda dapat berlari ke OOME sebagai kode Anda yang menyurvei ReferenceQueue dan membuang objek terkait mungkin terjadi tidak berjalan pada waktu yang tepat.
Jadi, keputusannya tergantung pada penggunaan - jika Anda menyimpan informasi yang mahal untuk dibuat, tetapi tetap dapat direkonstruksi dari data lain, gunakan referensi lunak - jika Anda menyimpan referensi ke contoh kanonik beberapa data, atau Anda ingin memiliki referensi ke objek tanpa "memiliki" itu (sehingga mencegahnya dari menjadi GC), gunakan referensi yang lemah.
Sangat berguna untuk penjelasan kapan benda lemah akan digunakan.
Jack BeNimble
Poin kunci tentang penggunaan yang benar dari a WeakReferenceadalah bahwa di tempat-tempat di mana seseorang harus menggunakannya, fakta bahwa seseorang dapat tetap valid untuk sementara waktu setelah referensi keluar dari ruang lingkup dapat ditoleransi, tetapi tidak diinginkan.
supercat
Saya berjuang untuk memahami apa gunanya WeakHashMap jika selalu menghasilkan referensi yang lemah ke objek nilai utamanya?
@supercat, Hanya ada satu penggunaan yang tepat WeakReferenceuntuk mengamati GC berjalan. Lihat elaborasi: stackoverflow.com/a/46291143/632951
Pacerier
1
@Pacerier: Penulis postingan itu salah besar. Dia mengabaikan beberapa skenario penggunaan lain seperti berlangganan acara, poin kedua tidak masuk akal, dan poin ketiga mengasumsikan bahwa seorang programmer dapat melakukan hal-hal yang tidak mungkin dilakukan. Poin pertamanya adalah masuk akal, tetapi berhubungan langsung dengan apa yang saya katakan. Jika kode sering harus membangun dan membandingkan objek besar yang tidak dapat diubah, misalnya, bagian bangunan akan sering lebih murah jika kode membuat objek baru tanpa memperhatikan apakah mereka sudah ada, tetapi perbandingan antara objek dan dirinya sendiri (referensi yang identik) akan ...
supercat
155
Di jawa ; urutan dari yang terkuat ke terlemah, ada: Kuat, Lembut, Lemah dan Phantom
Sebuah referensi yang kuat adalah referensi yang normal yang melindungi objek yang dirujuk dari koleksi oleh GC. yaitu Jangan pernah mengumpulkan sampah.
Sebuah referensi lembut memenuhi syarat untuk koleksi oleh kolektor sampah, tapi mungkin tidak akan dikumpulkan sampai memori yang dibutuhkan. yaitu mengumpulkan sampah sebelumnyaOutOfMemoryError .
Sebuah referensi Lemah adalah referensi yang tidak melindungi objek direferensikan dari koleksi oleh GC. yaitu sampah mengumpulkan ketika tidak ada referensi yang Kuat atau Lunak.
Sebuah referensi phantom adalah referensi ke suatu objek phantomly dirujuk setelah itu telah diselesaikan, tapi sebelum memori yang dialokasikan telah direklamasi.
Referensi lembut ... until memory is availabletidak masuk akal. Apakah yang Anda maksud is eligible for collection by garbage collector, but probably won't be collected until its memory is needed for another use?
ToolmakerSteve
1
ya, pemulung tidak akan mengumpulkan referensi sampai memori tersedia.
Premraj
2
Saya suka hal-hal yang dijelaskan sederhana, tanpa terlalu banyak bla bla +1 dari saya!
Prinsip:weak reference terkait dengan pengumpulan sampah. Biasanya, objek yang memiliki satu atau lebih referencetidak akan memenuhi syarat untuk pengumpulan sampah.
Prinsip di atas tidak berlaku ketika itu weak reference. Jika suatu objek hanya memiliki referensi yang lemah dengan objek lain, maka siap untuk pengumpulan sampah.
Mari kita lihat contoh di bawah ini: Kami memiliki MapObjek dengan mana Kunci adalah referensi objek.
import java.util.HashMap;publicclassTest{publicstaticvoid main(String args[]){HashMap<Employee,EmployeeVal> aMap =newHashMap<Employee,EmployeeVal>();Employee emp =newEmployee("Vinoth");EmployeeVal val =newEmployeeVal("Programmer");
aMap.put(emp, val);
emp =null;System.gc();System.out.println("Size of Map"+ aMap.size());}}
Sekarang, selama pelaksanaan program yang telah kami buat emp = null. The Mapholding kunci tidak masuk akal di sini seperti null. Dalam situasi di atas, objek bukan sampah yang dikumpulkan.
WeakHashMap
WeakHashMapadalah tempat entri ( key-to-value mappings) akan dihapus ketika tidak mungkin lagi untuk mengambilnya dariMap .
Biarkan saya menunjukkan contoh di atas sama dengan WeakHashMap
import java.util.WeakHashMap;publicclassTest{publicstaticvoid main(String args[]){WeakHashMap<Employee,EmployeeVal> aMap =newWeakHashMap<Employee,EmployeeVal>();Employee emp =newEmployee("Vinoth");EmployeeVal val =newEmployeeVal("Programmer");
aMap.put(emp, val);
emp =null;System.gc();int count =0;while(0!= aMap.size()){++count;System.gc();}System.out.println("Took "+ count
+" calls to System.gc() to result in weakHashMap size of : "+ aMap.size());}}
Output: Diperlukan 20 calls to System.gc()untuk menghasilkan aMap size: 0.
WeakHashMaphanya memiliki referensi lemah ke kunci, bukan referensi kuat seperti Mapkelas lainnya . Ada beberapa situasi yang harus Anda perhatikan ketika nilai atau kunci sangat direferensikan meskipun Anda telah menggunakannya WeakHashMap. Ini dapat dihindari dengan membungkus objek dalam Referensi Lemah .
Soft Referencesedikit lebih kuat dari referensi yang lemah. Referensi lunak memungkinkan pengumpulan sampah, tetapi meminta pengumpul sampah untuk menghapusnya hanya jika tidak ada pilihan lain.
Pengumpul sampah tidak secara agresif mengumpulkan benda-benda yang dapat dijangkau dengan lembut seperti halnya dengan benda-benda yang dapat dijangkau dengan lemah - melainkan hanya mengumpulkan benda-benda yang dapat dijangkau dengan lembut jika benar-benar "membutuhkan" memori. Referensi lembut adalah cara untuk mengatakan kepada pengumpul sampah, "Selama ingatan tidak terlalu ketat, saya ingin menyimpan benda ini. Tetapi jika ingatan menjadi sangat ketat, silakan mengumpulkannya dan saya akan berurusan. dengan itu." Pengumpul sampah diharuskan untuk menghapus semua referensi lunak sebelum dapat dibuang OutOfMemoryError.
Anda mungkin bisa NullPointerExceptionmasuk aMap.get().put(...).
xehpuk
Contoh HashMap pertama Anda terlihat salah. Ketika Anda melakukan "aMap.put (emp, val);" 'emp' dan 'val' adalah referensi yang kuat. Secara internal, variabel baru dibuat untuk menahan 'emp' dan 'val' jadi ketika Anda melakukan "emp = null;" Anda hanya membatalkan variabel "emp", tetapi bukan variabel secara internal ke peta hash (yang masih memegang objek Karyawan asli). Oleh karena itu peta hash masih akan memiliki referensi yang kuat untuk 'emp' terlepas dari apa yang Anda lakukan dengan variabel 'emp' di luar.
Tiago
@Tiago. Tidak. Mungkin dengan "contoh pertama" Anda merujuk pada WeakHashMapcontoh (karena itu adalah yang pertama yang menunjukkan perilaku Lemah). Lihatlah doc untuk "WeakHashMap": "An entry in a WeakHashMap will automatically be removed when its key is no longer in ordinary use. " Inti dari menggunakan WeakHashMap adalah bahwa Anda tidak harus mendeklarasikan / pass-in WeakReference; WeakHashMap melakukan itu untuk Anda, secara internal. docs.oracle.com/javase/7/docs/api/java/util/WeakHashMap.html
ToolmakerSteve
Mengambil 0 panggilan ke System.gc () untuk menghasilkan ukuran lemahHashMap dari: 0 adalah output dari program kedua Anda?
Satu-satunya perbedaan nyata antara referensi lunak dan referensi lemah adalah itu
pemulung menggunakan algoritma untuk memutuskan apakah akan mengambil kembali objek yang dapat dijangkau dengan lembut atau tidak, tetapi selalu mengklaim kembali objek yang dapat dijangkau dengan lemah.
SoftReferencedirancang untuk cache. Ketika ditemukan bahwa WeakReferencereferensi merupakan objek yang tidak dapat dijangkau, maka objek tersebut akan segera dihapus. SoftReferencedapat dibiarkan apa adanya. Biasanya ada beberapa algoritma yang berkaitan dengan jumlah memori bebas dan waktu yang terakhir digunakan untuk menentukan apakah harus dibersihkan. Algoritma Sun saat ini adalah untuk menghapus referensi jika belum digunakan dalam beberapa detik karena ada megabita memori bebas di heap Java (dapat dikonfigurasi, server HotSpot memeriksa terhadap kemungkinan tumpukan maksimum yang ditetapkan oleh -Xmx). SoftReferences akan dibersihkan sebelum OutOfMemoryErrordibuang, kecuali jika tidak dapat dijangkau.
@DoctororDrive tbf pertanyaannya adalah tentang java, bukan dalvik! :-P
fabspro
2
@YaroslavMytkalyk, Terus terang, jika Android ingin menulis ulang perilaku kelas, ia harus menggunakan namespace sendiri, bukan java.lang. Penyalahgunaan sinonim semacam itu tidak bermanfaat bagi siapa pun.
Pacerier
9
Artikel ini bisa sangat membantu untuk memahami referensi yang kuat, lembut, lemah dan phantom.
Untuk memberi Anda ringkasan,
Jika Anda hanya memiliki referensi yang lemah ke suatu 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.
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 mengecualikan 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 lain 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
Per dokumen tersebut , Referensi Lemah longgar harus dibersihkan dengan GC berjalan.
Per dokumen , SoftReferences yang longgar harus dihapus sebelum OOM dilemparkan.
Itulah satu-satunya perbedaan nyata. Yang lainnya bukan bagian dari kontrak. (Saya akan menganggap dokumen terbaru adalah kontrak.)
Referensi Soft berguna. Cache yang peka terhadap memori menggunakan SoftReferences, bukan WeakReferences.
Satu-satunya penggunaan WeakReference yang tepat adalah mengamati jalannya GC. Anda melakukan ini dengan membuat WeakReference baru yang objeknya segera keluar dari ruang lingkup, kemudian mencoba untuk mendapatkan nol weak_ref.get(). Saat itu null, Anda mengetahui bahwa di antara durasi ini, GC berjalan.
Adapun salah penggunaan WeakReference, daftar ini tak ada habisnya:
peretasan yang buruk untuk mengimplementasikan prioritas-2 softreference sehingga Anda tidak perlu menulis satu, namun itu tidak berfungsi seperti yang diharapkan karena cache akan dihapus pada setiap proses GC, bahkan ketika ada memori cadangan. Lihat https://stackoverflow.com/a/3243242/632951 untuk menelepon. (Selain itu, bagaimana jika Anda membutuhkan lebih dari 2 tingkat prioritas cache? Anda masih harus memiliki perpustakaan nyata untuk itu.)
peretasan yang buruk untuk mengaitkan data dengan objek dari kelas yang ada, namun itu menciptakan kebocoran memori (OutOfMemoryError) ketika GC Anda memutuskan untuk mengambil istirahat setelah referensi Anda dibuat. Selain itu, ini sangat buruk: Pendekatan yang lebih baik adalah menggunakan tuple.
peretasan yang buruk untuk mengaitkan data dengan objek dari kelas yang ada, di mana kelas memiliki keberanian untuk menjadikan dirinya non-subclassable, dan digunakan dalam kode fungsi yang ada yang perlu Anda panggil. Dalam kasus seperti itu, solusi yang tepat adalah mengedit kelas dan menjadikannya subclassable, atau mengedit fungsi dan membuatnya mengambil antarmuka alih-alih kelas, atau menggunakan fungsi alternatif.
Bagaimana dengan cache di mana jenis kunci itu equals()hanya identitas objek? Referensi lunak tampak seperti pemborosan di sana, karena sekali objek kunci tidak lagi dapat dijangkau dengan kuat, tidak akan ada yang melihat pemetaan itu lagi.
HighCommander4
Saya tidak setuju. Gunakan WeakReference saat Anda tidak ingin memengaruhi GC dengan cara apa pun (Anda mungkin ingin menyimpan referensi objek dan kemudian mengeceknya jika masih ada, tanpa preferensi apa pun yang ada). Gunakan SoftReference jika Anda ingin mempengaruhi GC untuk mencoba dan menjaga objek (yaitu ketika Anda lebih suka bahwa GC akan menyimpannya).
David Refaeli
Contoh yang baik di mana menggunakan WeakReference ada di Android AsyncTask - untuk menjaga instance konteks. Dengan begitu jika konteksnya mati (jika aktivitas - rotasi layar, dll.), AsyncTask tidak akan memiliki referensi yang kuat untuk itu, dan itu bisa menjadi sampah yang dikumpulkan. Periksa youtu.be/…
David Refaeli
3
Enam jenis status jangkauan objek di Jawa:
Benda kuat yang dapat dijangkau - GC tidak akan mengumpulkan (mengambil kembali memori yang ditempati ) objek semacam ini. Ini dapat dijangkau melalui simpul akar atau objek lain yang sangat terjangkau (yaitu melalui variabel lokal, variabel kelas, variabel contoh, dll.)
Objek yang dapat dijangkau lunak - GC mungkin berupaya mengumpulkan objek semacam ini tergantung pada pertentangan memori. Ini dapat dijangkau dari root melalui satu atau lebih objek referensi lunak
Benda lemah yang dapat dijangkau - GC harus mengumpulkan benda semacam ini. Ini dapat dijangkau dari root melalui satu atau lebih objek referensi yang lemah
Objek yang dapat dibangkitkan - GC sudah dalam proses mengumpulkan objek-objek ini. Tetapi mereka mungkin kembali ke salah satu negara bagian - Kuat / Lembut / Lemah dengan eksekusi beberapa finalizer
Objek yang dapat dijangkau phantom - GC sudah dalam proses mengumpulkan objek-objek ini dan telah memutuskan untuk tidak dapat dibangkitkan oleh finalizer mana pun (jika ia mendeklarasikan metode finalize () itu sendiri, maka finalizer-nya akan dijalankan) . Ini dapat dijangkau dari root melalui satu atau lebih objek referensi hantu
Unreachable objek - Sebuah objek yang tidak kuat, lembut, lemah, atau hantu terjangkau, dan tidak resurrectable. Objek-objek ini siap untuk reklamasi
Bukan deskripsi yang baik tentang referensi hantu. Selain itu, Anda telah mencantumkan 4 jenis dalam urutan yang aneh. "phantom" adalah tipe terlemah, bukan tipe terkuat. Urutan tradisional untuk daftar ini adalah "kuat, lunak, lemah, hantu". Dan saya tidak tahu dari mana Anda mendapatkan gagasan bahwa objek hantu digunakan untuk mekanisme caching. AFAIK, mereka adalah keadaan sementara yang hanya dilihat oleh GC, bukan sesuatu yang akan bekerja dengan programmer biasa.
ToolmakerSteve
@ToolmakerSteve dan semuanya - Permintaan maaf untuk beberapa hal 1. penjelasan referensi Phantom yang salah dalam versi sebelumnya dari jawaban saya, dan 2. Keterlambatan dalam mengoreksi kesalahan. Sekarang jawabannya telah diperbaiki dengan memperbaiki kesalahan
V.Vidyasagar
1
Orang harus menyadari bahwa objek yang direferensikan dengan lemah hanya akan dikumpulkan ketika memiliki HANYA referensi yang lemah. Jika memiliki sebanyak satu referensi yang kuat, itu tidak akan terkumpul tidak peduli berapa banyak referensi lemah yang dimilikinya.
Ini adalah akal sehat ... hal yang sama berlaku untuk softref dan phantomref.
Pacerier
1
Untuk memberikan aspek penggunaan memori dalam aksi, saya melakukan percobaan dengan referensi Strong, Soft, Weak & Phantom di bawah beban berat dengan benda berat dengan mempertahankannya sampai akhir program. Kemudian memonitor penggunaan tumpukan & perilaku GC . Metrik ini dapat bervariasi berdasarkan kasus per kasus, tetapi tentunya memberikan pemahaman tingkat tinggi. Di bawah ini adalah temuan.
Heap & GC Perilaku di bawah beban berat
Referensi Kuat / Keras - Saat program berlanjut, JVM tidak dapat mengumpulkan objek referensi kuat yang dipertahankan. Akhirnya berakhir di "java.lang.OutOfMemoryError: Java heap space"
Referensi Lunak - Ketika program berlanjut, penggunaan tumpukan terus bertambah, tetapi OLD gen GC terjadi saat itu mendekati tumpukan maksimum. GC mulai sedikit terlambat setelah memulai program.
Referensi Lemah - Saat program dimulai, objek mulai menyelesaikan & segera dikumpulkan. Sebagian besar benda dikumpulkan dalam pengumpulan sampah generasi muda.
Referensi Phantom - Mirip dengan referensi lemah, objek referensi hantu juga mulai diselesaikan & sampah segera dikumpulkan. Tidak ada GC generasi lama & semua benda dikumpulkan dalam pengumpulan sampah generasi muda itu sendiri.
Jawaban:
Dari Memahami Lemah Referensi , oleh Ethan Nicholas:
Dan Peter Kessler menambahkan dalam komentar:
sumber
Referensi yang lemah dikumpulkan dengan penuh semangat. Jika GC menemukan bahwa suatu objek dapat dijangkau dengan lemah (dapat dicapai hanya melalui referensi yang lemah), itu akan menghapus referensi yang lemah ke objek itu dengan segera. Dengan demikian, mereka baik untuk menyimpan referensi ke objek yang juga disimpan oleh program Anda (sangat direferensikan) "informasi terkait", seperti informasi refleksi yang di-cache tentang kelas, atau pembungkus untuk objek, dll. Apa pun yang membuat tidak masuk akal untuk menjaga setelah objek itu dikaitkan dengan GC-ed. Ketika referensi yang lemah dihapus, itu akan enqueued dalam antrian referensi bahwa jajak pendapat kode Anda di suatu tempat, dan itu membuang objek terkait juga. Artinya, Anda menyimpan informasi tambahan tentang suatu objek, tetapi informasi itu tidak diperlukan begitu objek yang dirujuknya pergi. Sebenarnya, dalam situasi tertentu Anda bahkan dapat subkelas WeakReference dan menyimpan informasi tambahan terkait tentang objek di bidang subkelas WeakReference. Penggunaan WeakReference yang khas lainnya adalah bersama dengan Maps untuk menjaga instance kanonik.
SoftReferences di sisi lain baik untuk menyimpan sumber daya eksternal yang dapat diolah kembali karena GC biasanya menunda untuk menghapusnya. Namun dijamin bahwa semua SoftReferences akan dihapus sebelum OutOfMemoryError dilempar, sehingga secara teoritis mereka tidak dapat menyebabkan OOME [*].
Contoh kasus penggunaan umum adalah menyimpan bentuk konten yang diurai dari file. Anda akan menerapkan sistem tempat Anda memuat file, menguraikannya, dan menyimpan SoftReference ke objek root dari representasi yang diuraikan. Lain kali Anda membutuhkan file, Anda akan mencoba mengambilnya melalui SoftReference. Jika Anda dapat mengambilnya, Anda membebaskan diri dari beban / parse lain, dan jika GC menghapusnya sementara itu, Anda memuatnya kembali. Dengan begitu, Anda menggunakan memori bebas untuk pengoptimalan kinerja, tetapi jangan mengambil risiko OOME.
Sekarang untuk [*]. Menyimpan SoftReference tidak dapat menyebabkan OOME sendiri. Jika di sisi lain Anda secara keliru menggunakan SoftReference untuk suatu tugas, sebuah WeakReference dimaksudkan untuk digunakan (yaitu, Anda menyimpan informasi yang terkait dengan Objek yang entah bagaimana sangat dirujuk, dan membuangnya ketika objek Referensi dihapus), Anda dapat berlari ke OOME sebagai kode Anda yang menyurvei ReferenceQueue dan membuang objek terkait mungkin terjadi tidak berjalan pada waktu yang tepat.
Jadi, keputusannya tergantung pada penggunaan - jika Anda menyimpan informasi yang mahal untuk dibuat, tetapi tetap dapat direkonstruksi dari data lain, gunakan referensi lunak - jika Anda menyimpan referensi ke contoh kanonik beberapa data, atau Anda ingin memiliki referensi ke objek tanpa "memiliki" itu (sehingga mencegahnya dari menjadi GC), gunakan referensi yang lemah.
sumber
WeakReference
adalah bahwa di tempat-tempat di mana seseorang harus menggunakannya, fakta bahwa seseorang dapat tetap valid untuk sementara waktu setelah referensi keluar dari ruang lingkup dapat ditoleransi, tetapi tidak diinginkan.WeakReference
untuk mengamati GC berjalan. Lihat elaborasi: stackoverflow.com/a/46291143/632951Di jawa ; urutan dari yang terkuat ke terlemah, ada: Kuat, Lembut, Lemah dan Phantom
Sebuah referensi yang kuat adalah referensi yang normal yang melindungi objek yang dirujuk dari koleksi oleh GC. yaitu Jangan pernah mengumpulkan sampah.
Sebuah referensi lembut memenuhi syarat untuk koleksi oleh kolektor sampah, tapi mungkin tidak akan dikumpulkan sampai memori yang dibutuhkan. yaitu mengumpulkan sampah sebelumnya
OutOfMemoryError
.Sebuah referensi Lemah adalah referensi yang tidak melindungi objek direferensikan dari koleksi oleh GC. yaitu sampah mengumpulkan ketika tidak ada referensi yang Kuat atau Lunak.
Sebuah referensi phantom adalah referensi ke suatu objek phantomly dirujuk setelah itu telah diselesaikan, tapi sebelum memori yang dialokasikan telah direklamasi.
Sumber
Analogi: Anggap JVM adalah sebuah kerajaan, Obyek adalah raja kerajaan, dan GC adalah seorang penyerang kerajaan yang mencoba membunuh raja (objek).
sumber
until memory is available
tidak masuk akal. Apakah yang Anda maksudis eligible for collection by garbage collector, but probably won't be collected until its memory is needed for another use
?Referensi Lemah http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ref/WeakReference.html
Prinsip:
weak reference
terkait dengan pengumpulan sampah. Biasanya, objek yang memiliki satu atau lebihreference
tidak akan memenuhi syarat untuk pengumpulan sampah.Prinsip di atas tidak berlaku ketika itu
weak reference
. Jika suatu objek hanya memiliki referensi yang lemah dengan objek lain, maka siap untuk pengumpulan sampah.Mari kita lihat contoh di bawah ini: Kami memiliki
Map
Objek dengan mana Kunci adalah referensi objek.Sekarang, selama pelaksanaan program yang telah kami buat
emp = null
. TheMap
holding kunci tidak masuk akal di sini sepertinull
. Dalam situasi di atas, objek bukan sampah yang dikumpulkan.WeakHashMap
WeakHashMap
adalah tempat entri (key-to-value mappings
) akan dihapus ketika tidak mungkin lagi untuk mengambilnya dariMap
.Biarkan saya menunjukkan contoh di atas sama dengan WeakHashMap
Output: Diperlukan
20 calls to System.gc()
untuk menghasilkanaMap size
: 0.WeakHashMap
hanya memiliki referensi lemah ke kunci, bukan referensi kuat sepertiMap
kelas lainnya . Ada beberapa situasi yang harus Anda perhatikan ketika nilai atau kunci sangat direferensikan meskipun Anda telah menggunakannyaWeakHashMap
. Ini dapat dihindari dengan membungkus objek dalam Referensi Lemah .Referensi Lembut.
Soft Reference
sedikit lebih kuat dari referensi yang lemah. Referensi lunak memungkinkan pengumpulan sampah, tetapi meminta pengumpul sampah untuk menghapusnya hanya jika tidak ada pilihan lain.Pengumpul sampah tidak secara agresif mengumpulkan benda-benda yang dapat dijangkau dengan lembut seperti halnya dengan benda-benda yang dapat dijangkau dengan lemah - melainkan hanya mengumpulkan benda-benda yang dapat dijangkau dengan lembut jika benar-benar "membutuhkan" memori. Referensi lembut adalah cara untuk mengatakan kepada pengumpul sampah, "Selama ingatan tidak terlalu ketat, saya ingin menyimpan benda ini. Tetapi jika ingatan menjadi sangat ketat, silakan mengumpulkannya dan saya akan berurusan. dengan itu." Pengumpul sampah diharuskan untuk menghapus semua referensi lunak sebelum dapat dibuang
OutOfMemoryError
.sumber
NullPointerException
masukaMap.get().put(...)
.WeakHashMap
contoh (karena itu adalah yang pertama yang menunjukkan perilaku Lemah). Lihatlah doc untuk "WeakHashMap":"An entry in a WeakHashMap will automatically be removed when its key is no longer in ordinary use. "
Inti dari menggunakan WeakHashMap adalah bahwa Anda tidak harus mendeklarasikan / pass-in WeakReference; WeakHashMap melakukan itu untuk Anda, secara internal. docs.oracle.com/javase/7/docs/api/java/util/WeakHashMap.htmlWeakHashMap
dalam aksi, dengan contoh aplikasi yang menunjukkan bagaimana entri dihapus hanya setelah pengumpulan sampah dijalankan, lihat Jawaban saya untuk Pertanyaan, Apakah WeakHashMap terus berkembang, atau apakah itu menghapus kunci sampah? .Satu-satunya perbedaan nyata antara referensi lunak dan referensi lemah adalah itu
sumber
SoftReference
dirancang untuk cache. Ketika ditemukan bahwaWeakReference
referensi merupakan objek yang tidak dapat dijangkau, maka objek tersebut akan segera dihapus.SoftReference
dapat dibiarkan apa adanya. Biasanya ada beberapa algoritma yang berkaitan dengan jumlah memori bebas dan waktu yang terakhir digunakan untuk menentukan apakah harus dibersihkan. Algoritma Sun saat ini adalah untuk menghapus referensi jika belum digunakan dalam beberapa detik karena ada megabita memori bebas di heap Java (dapat dikonfigurasi, server HotSpot memeriksa terhadap kemungkinan tumpukan maksimum yang ditetapkan oleh-Xmx
).SoftReference
s akan dibersihkan sebelumOutOfMemoryError
dibuang, kecuali jika tidak dapat dijangkau.sumber
java.lang
. Penyalahgunaan sinonim semacam itu tidak bermanfaat bagi siapa pun.Artikel ini bisa sangat membantu untuk memahami referensi yang kuat, lembut, lemah dan phantom.
Untuk memberi Anda ringkasan,
Jika Anda hanya memiliki referensi yang lemah ke suatu 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.
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 mengecualikan siklus GC dan akan direklamasi jika objek tidak memiliki referensi kuat lainnya).
Analogi 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 lain 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
sumber
Satu-satunya Perbedaan Nyata
Per dokumen tersebut , Referensi Lemah longgar harus dibersihkan dengan GC berjalan.
Per dokumen , SoftReferences yang longgar harus dihapus sebelum OOM dilemparkan.
Itulah satu-satunya perbedaan nyata. Yang lainnya bukan bagian dari kontrak. (Saya akan menganggap dokumen terbaru adalah kontrak.)
Referensi Soft berguna. Cache yang peka terhadap memori menggunakan SoftReferences, bukan WeakReferences.
Satu-satunya penggunaan WeakReference yang tepat adalah mengamati jalannya GC. Anda melakukan ini dengan membuat WeakReference baru yang objeknya segera keluar dari ruang lingkup, kemudian mencoba untuk mendapatkan nol
weak_ref.get()
. Saat itunull
, Anda mengetahui bahwa di antara durasi ini, GC berjalan.Adapun salah penggunaan WeakReference, daftar ini tak ada habisnya:
peretasan yang buruk untuk mengimplementasikan prioritas-2 softreference sehingga Anda tidak perlu menulis satu, namun itu tidak berfungsi seperti yang diharapkan karena cache akan dihapus pada setiap proses GC, bahkan ketika ada memori cadangan. Lihat https://stackoverflow.com/a/3243242/632951 untuk menelepon. (Selain itu, bagaimana jika Anda membutuhkan lebih dari 2 tingkat prioritas cache? Anda masih harus memiliki perpustakaan nyata untuk itu.)
peretasan yang buruk untuk mengaitkan data dengan objek dari kelas yang ada, namun itu menciptakan kebocoran memori (OutOfMemoryError) ketika GC Anda memutuskan untuk mengambil istirahat setelah referensi Anda dibuat. Selain itu, ini sangat buruk: Pendekatan yang lebih baik adalah menggunakan tuple.
peretasan yang buruk untuk mengaitkan data dengan objek dari kelas yang ada, di mana kelas memiliki keberanian untuk menjadikan dirinya non-subclassable, dan digunakan dalam kode fungsi yang ada yang perlu Anda panggil. Dalam kasus seperti itu, solusi yang tepat adalah mengedit kelas dan menjadikannya subclassable, atau mengedit fungsi dan membuatnya mengambil antarmuka alih-alih kelas, atau menggunakan fungsi alternatif.
sumber
equals()
hanya identitas objek? Referensi lunak tampak seperti pemborosan di sana, karena sekali objek kunci tidak lagi dapat dijangkau dengan kuat, tidak akan ada yang melihat pemetaan itu lagi.Enam jenis status jangkauan objek di Jawa:
Untuk detail lebih lanjut: https://www.artima.com/insidejvm/ed2/gc16.html «runtuh
sumber
Orang harus menyadari bahwa objek yang direferensikan dengan lemah hanya akan dikumpulkan ketika memiliki HANYA referensi yang lemah. Jika memiliki sebanyak satu referensi yang kuat, itu tidak akan terkumpul tidak peduli berapa banyak referensi lemah yang dimilikinya.
sumber
Untuk memberikan aspek penggunaan memori dalam aksi, saya melakukan percobaan dengan referensi Strong, Soft, Weak & Phantom di bawah beban berat dengan benda berat dengan mempertahankannya sampai akhir program. Kemudian memonitor penggunaan tumpukan & perilaku GC . Metrik ini dapat bervariasi berdasarkan kasus per kasus, tetapi tentunya memberikan pemahaman tingkat tinggi. Di bawah ini adalah temuan.
Heap & GC Perilaku di bawah beban berat
Anda dapat memperoleh lebih banyak dalam grafik, statistik, pengamatan mendalam untuk percobaan ini di sini .
sumber
WeakReference : objek yang hanya direferensikan dengan lemah dikumpulkan pada setiap siklus GC (kecil atau penuh).
SoftReference : ketika objek yang hanya direferensikan secara lembut dikumpulkan tergantung pada:
-XX: SoftRefLRUPolicyMSPerMB = N flag (nilai default adalah 1000, alias 1 detik)
Jumlah memori bebas di heap.
Contoh:
Kemudian objek yang dirujuk hanya oleh SoftReference akan dikumpulkan jika terakhir kali diakses lebih dari 10 detik.
sumber