Dari pemahaman saya, pengumpulan sampah di Jawa membersihkan beberapa objek jika tidak ada yang 'menunjuk' ke objek itu.
Pertanyaan saya adalah, apa yang terjadi jika kita memiliki sesuatu seperti ini:
class Node {
public object value;
public Node next;
public Node(object o, Node n) { value = 0; next = n;}
}
//...some code
{
Node a = new Node("a", null),
b = new Node("b", a),
c = new Node("c", b);
a.next = c;
} //end of scope
//...other code
a
,, b
dan c
harus dikumpulkan, tetapi semuanya dirujuk oleh objek lain.
Bagaimana cara pengumpulan sampah Jawa menangani ini? (Atau itu hanya menguras memori?)
java
garbage-collection
AlexeyMK
sumber
sumber
Jawaban:
GC Jawa menganggap objek "sampah" jika tidak dapat dijangkau melalui rantai mulai dari akar pengumpulan sampah, sehingga objek ini akan dikumpulkan. Meskipun objek dapat menunjuk satu sama lain untuk membentuk siklus, mereka tetap sampah jika terpotong dari akar.
Lihat bagian tentang benda-benda yang tidak dapat dijangkau di Lampiran A: Kebenaran Tentang Pengumpulan Sampah di Java Platform Performance: Strategi dan Taktik untuk detail berdarah.
sumber
ya pengumpul Sampah Jawa menangani referensi melingkar!
Ada benda-benda khusus yang disebut akar pengumpulan sampah (GC root). Ini selalu dapat dijangkau dan begitu pula objek apa pun yang memiliki mereka pada akarnya sendiri.
Aplikasi Java sederhana memiliki akar GC berikut:
Untuk menentukan objek mana yang tidak lagi digunakan, JVM sebentar-sebentar menjalankan apa yang sangat tepat disebut algoritma mark-and-sweep . Ini berfungsi sebagai berikut
Jadi, jika ada objek yang tidak dapat dijangkau dari akar GC (bahkan jika itu direferensikan sendiri atau dirujuk siklik) itu akan dikenakan pengumpulan sampah.
Ofcourse kadang-kadang hal ini dapat menyebabkan kebocoran memori jika programmer lupa untuk merujuk objek.
Sumber: Manajemen Memori Java
sumber
Seorang pengumpul sampah dimulai dari beberapa tempat "root" yang selalu dianggap "dapat dijangkau", seperti register CPU, stack, dan variabel global. Ini bekerja dengan menemukan petunjuk di area tersebut, dan secara rekursif menemukan semua yang mereka tuju. Setelah itu ditemukan semua itu, segala sesuatu yang lain adalah sampah.
Tentu saja ada beberapa variasi, kebanyakan demi kecepatan. Sebagai contoh, sebagian besar pengumpul sampah modern adalah "generasi", yang berarti bahwa mereka membagi benda menjadi beberapa generasi, dan seiring bertambahnya usia, pengumpul sampah berjalan lebih lama dan lebih lama antara waktu yang mencoba untuk mencari tahu apakah benda itu masih valid atau tidak - itu hanya mulai berasumsi bahwa jika ia telah hidup lama, kemungkinannya cukup bagus bahwa ia akan terus hidup lebih lama lagi.
Meskipun demikian, ide dasarnya tetap sama: semuanya didasarkan pada mulai dari beberapa set root hal-hal yang diperlukan begitu saja masih dapat digunakan, dan kemudian mengejar semua petunjuk untuk menemukan apa lagi yang bisa digunakan.
Di samping menarik: semoga orang sering terkejut dengan tingkat kesamaan antara bagian pengumpul sampah dan kode untuk mengatur objek untuk hal-hal seperti panggilan prosedur jarak jauh. Dalam setiap kasus, Anda mulai dari beberapa root set objek, dan mengejar pointer untuk menemukan semua objek lain yang merujuk ...
sumber
Anda benar. Bentuk spesifik pengumpulan sampah yang Anda gambarkan disebut " penghitungan referensi ". Cara kerjanya (secara konseptual, setidaknya, sebagian besar implementasi modern penghitungan referensi sebenarnya diimplementasikan dengan sangat berbeda) dalam kasus yang paling sederhana, terlihat seperti ini:
Dan strategi sederhana ini memiliki masalah yang Anda jelaskan: jika A referensi B dan B referensi A, maka kedua jumlah referensi mereka tidak akan pernah kurang dari 1, yang berarti mereka tidak akan pernah dikumpulkan.
Ada empat cara untuk mengatasi masalah ini:
Ngomong-ngomong, cara utama lainnya untuk mengimplementasikan pengumpul sampah (dan saya sudah mengisyaratkan bahwa beberapa kali di atas), sedang melacak . Seorang kolektor tracing didasarkan pada konsep reachability . Anda mulai dengan beberapa set root yang Anda tahu selalu dapat dijangkau (konstanta global, misalnya, atau
Object
kelas, ruang lingkup leksikal saat ini, bingkai stack saat ini) dan dari sana Anda melacak semua objek yang dapat dijangkau dari set root, kemudian semua objek yang dapat dijangkau dari objek yang dapat dijangkau dari root set dan seterusnya, sampai Anda memiliki penutupan transitif. Segala sesuatu yang tidak ada dalam penutupan itu adalah sampah.Karena sebuah siklus hanya dapat dicapai dalam dirinya sendiri, tetapi tidak dapat dicapai dari set root, itu akan dikumpulkan.
sumber
Java GCs sebenarnya tidak berperilaku seperti yang Anda gambarkan. Lebih akurat untuk mengatakan bahwa mereka mulai dari satu set objek dasar, sering disebut "akar GC", dan akan mengumpulkan objek apa pun yang tidak dapat dijangkau dari root.
Akar GC mencakup hal-hal seperti:
Jadi, dalam kasus Anda, setelah variabel lokal a, b, dan c keluar dari ruang lingkup di akhir metode Anda, tidak ada lagi akar GC yang berisi, secara langsung atau tidak langsung, referensi ke salah satu dari tiga node Anda, dan mereka akan memenuhi syarat untuk pengumpulan sampah.
Tautan TofuBeer memiliki detail lebih banyak jika Anda menginginkannya.
sumber
Artikel ini (tidak lagi tersedia) membahas tentang pengumpul sampah (secara konseptual ... ada beberapa implementasi). Bagian yang relevan dengan posting Anda adalah "A.3.4 Tidak Dapat Dicapai":
sumber
Pengumpulan sampah biasanya tidak berarti "membersihkan beberapa objek jika tidak ada yang lain 'menunjuk' ke objek itu" (itu penghitungan referensi). Pengumpulan sampah secara kasar berarti menemukan benda yang tidak dapat dijangkau dari program.
Jadi, dalam contoh Anda, setelah a, b, dan c keluar dari ruang lingkup, mereka dapat dikumpulkan oleh GC, karena Anda tidak dapat mengakses objek ini lagi.
sumber
Bill menjawab pertanyaan Anda secara langsung. Seperti yang dikatakan Amnon, definisi Anda tentang pengumpulan sampah hanyalah penghitungan referensi. Saya hanya ingin menambahkan bahwa bahkan algoritma yang sangat sederhana seperti mark dan sweep serta koleksi salin dengan mudah menangani referensi melingkar. Jadi, tidak ada yang ajaib tentang itu!
sumber