Apa perbedaan antara java.lang.ref.WeakReference
dan java.lang.ref.SoftReference
?
Apa perbedaan antara java.lang.ref.WeakReference
dan java.lang.ref.SoftReference
?
Jawaban:
Dari Memahami Lemah Referensi , oleh Ethan Nicholas:
Referensi yang lemah
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:
WeakReference weakWidget = new WeakReference(widget);
dan kemudian di tempat lain dalam kode yang dapat Anda gunakan
weakWidget.get()
untuk mendapatkan yang sebenarnyaWidget
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) yangweakWidget.get()
tiba - tiba mulai kembalinull
....
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.
SoftReferences
tidak diharuskan untuk berperilaku berbeda dari ituWeakReferences
, 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.
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.
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/632951
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.
Analogi: Anggap JVM adalah sebuah kerajaan, Obyek adalah raja kerajaan, dan GC adalah seorang penyerang kerajaan yang mencoba membunuh raja (objek).
until memory is available
tidak 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
?
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 lebih reference
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.
import java.util.HashMap;
public class Test {
public static void main(String args[]) {
HashMap<Employee, EmployeeVal> aMap = new
HashMap<Employee, EmployeeVal>();
Employee emp = new Employee("Vinoth");
EmployeeVal val = new EmployeeVal("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 Map
holding kunci tidak masuk akal di sini seperti null
. 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
import java.util.WeakHashMap;
public class Test {
public static void main(String args[]) {
WeakHashMap<Employee, EmployeeVal> aMap =
new WeakHashMap<Employee, EmployeeVal>();
Employee emp = new Employee("Vinoth");
EmployeeVal val = new EmployeeVal("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.
WeakHashMap
hanya memiliki referensi lemah ke kunci, bukan referensi kuat seperti Map
kelas 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 .
import java.lang.ref.WeakReference;
import java.util.HashMap;
public class Test {
public static void main(String args[]) {
HashMap<Employee, EmployeeVal> map =
new HashMap<Employee, EmployeeVal>();
WeakReference<HashMap<Employee, EmployeeVal>> aMap =
new WeakReference<HashMap<Employee, EmployeeVal>>(
map);
map = null;
while (null != aMap.get()) {
aMap.get().put(new Employee("Vinoth"),
new EmployeeVal("Programmer"));
System.out.println("Size of aMap " + aMap.get().size());
System.gc();
}
System.out.println("Its garbage collected");
}
}
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
.
NullPointerException
masuk aMap.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.html
WeakHashMap
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
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.
SoftReference
dirancang untuk cache. Ketika ditemukan bahwa WeakReference
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 sebelum OutOfMemoryError
dibuang, kecuali jika tidak dapat dijangkau.
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
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.
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.
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
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.
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 .
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.