"Bună! Am decis să vă mai dau o mică lecție despre colectarea gunoiului."

După cum știți deja, mașina Java în sine monitorizează când un obiect devine inutil și îl șterge.

"Da. Tu și Rishi mi-ai spus despre asta mai devreme. Nu-mi amintesc detaliile."

— Bine. Atunci hai să trecem din nou peste asta.

Colectarea gunoiului - 1

„De îndată ce un obiect este creat, JVM-ul alocă memorie pentru acesta. Interesul pentru obiect este monitorizat folosind variabile de referință.  Un obiect poate fi șters în timpul colectării gunoiului, adică procedura prin care memoria este eliberată dacă nu există variabile care să facă referire la obiect.

— Povestește-mi puțin despre gunoiul — ce este și cum funcționează.

"OK. Colectarea gunoiului se întâmpla pe firul principal. La fiecare 5 minute sau mai des. Dacă nu era vreodată suficientă memorie liberă, mașina Java suspenda toate firele și ștergea obiectele neutilizate."

„Dar această abordare a fost abandonată acum. Colectorul de gunoi de nouă generație lucrează în culise și pe un fir separat. Aceasta se numește colectarea concomitentă a gunoiului”.

"Îmi dau seama. Cum se ia mai exact decizia de a șterge sau nu un obiect?"

„Numărarea numărului de referințe la un obiect nu este foarte eficientă – pot exista obiecte care se referă unele la altele, dar nu sunt referite de alte obiecte.”

„Așadar, Java adoptă o abordare diferită.  Java împarte obiectele în accesibile și inaccesibile.  Un obiect este accesibil (viu) dacă este referit de un alt obiect accesibil (viu). Accesibilitatea este determinată din fire de execuție. , chiar dacă nimeni nu le face referire.”

"OK. Cred că am înțeles."

„Cum are loc colectarea gunoiului efectiv – ștergerea obiectelor inutile?”

"Este simplu. În Java, memoria este împărțită în două părți prin convenție, iar când este timpul pentru colectarea gunoiului, toate obiectele vii (accesibile) sunt copiate într-o altă parte a memoriei, iar vechea memorie este eliberată în totalitate."

"Aceasta este o abordare interesantă. Nu este nevoie să numărați referințele: copiați toate obiectele accesibile și totul este gunoi."

„Este ceva mai complicat decât atât. Programatorii Java au descoperit că obiectele sunt de obicei împărțite în două categorii: cu durată lungă de viață (care există pe tot parcursul timpului în care programul rulează) și de scurtă durată (care sunt necesare în metode și pentru efectuarea «locală). » operațiuni)."

„Este mult mai eficient să ținem obiectele cu viață lungă separate de cele cu viață scurtă. Pentru a face acest lucru, a fost necesar să găsim o modalitate de a determina longevitatea obiectului”.

„Așadar, au împărțit toată memoria în „generații”. Există obiecte de prima generație, obiecte de a doua generație etc. De fiecare dată când memoria este șters, contorul de generație este incrementat cu 1. Dacă anumite obiecte există în mai multe generații, atunci ele sunt înregistrate ca longevive.”

„Astăzi, colectorul de gunoi este o parte foarte complexă și eficientă a Java. Multe dintre părțile sale funcționează euristic, pe baza unor algoritmi care fac presupuneri. Drept urmare, adesea „nu ascultă” utilizatorul.”

"Sens?"

„Java are un obiect de colectare a gunoiului ( GC ) care poate fi apelat folosind metoda System.gc ()”.

„Puteți folosi și System.runFinalization() pentru a forța apelurile la metodele de finalizare a obiectelor care urmează să fie șterse. Dar adevărul este că, conform documentației Java, aceasta garantează nici că colectarea gunoiului va începe, nici că finalize( ) va fi apelată.  Colectorul de gunoi decide când să o apeleze și despre ce. "

"Uau! Bine de știut."

"Dar sunt mai multe. După cum știți, în Java, unele obiecte fac referire la altele. Această rețea de referințe este folosită pentru a determina dacă un obiect trebuie șters."

"Și, uite. Java are referințe speciale care te permit să influențezi acest proces. Există clase speciale de wrapper pentru ei. Iată-le:"

SoftReference  este o referință soft.”

WeakReference  este o referință slabă”.

" PhantomReference este o referință fantomă."

"Uh... Asta îmi amintește de clasele interioare, de clasele imbricate, de clasele anonime imbricate și de clasele locale. Numele sunt diferite, dar nu este deloc clar pentru ce sunt."

„Spune, Amigo, ai devenit programator. Acum ești supărat din cauza numelor de clasă, spunând „nu sunt suficient de informative și este imposibil cu un singur nume(!) să determinați ce face această clasă, cum, și de ce"."

"Uau. Nici măcar nu am observat. Dar este atât de evident."

"OK. Destul de cuvinte. Să-ți spun despre SoftReferences."

„Aceste referințe au fost concepute special pentru stocarea în cache, deși pot fi folosite în alte scopuri — toate la discreția programatorului.”

„Iată un exemplu de astfel de referință:”

Exemplu
// Create a Cat object
Cat cat = new Cat();

// Create a soft reference to a Cat object
SoftReference<Cat> catRef = new SoftReference<Cat>(cat);

// Now only the catRef soft reference points at the object
cat = null;

// Now the ordinary cat variable also references the object
cat = catRef.get();

// Clear the soft reference
catRef.clear();

„Dacă singurele referințe la un obiect sunt blânde, atunci acesta continuă să trăiască și se numește „acces ușor”.

„Dar!  Un obiect la care se face referire numai prin referințe soft poate fi șters de către garbage collector dacă programul nu are suficientă memorie.  Dacă dintr-o dată programul nu are suficientă memorie, înainte de a arunca o OutOfMemoryException , garbage collectorul va șterge toate obiectele referit prin referințe soft și va încerca din nou să aloce memorie programului."

„Să presupunem că un program client solicită frecvent diferite date de la un program server. Programul server poate folosi o SoftReference pentru a stoca în cache unele dintre ele. Dacă obiectele ținute de moarte prin referințe soft ocupă o mare parte din memorie, atunci colectorul de gunoi le șterge pur și simplu. toate. E frumos!"

— Da. Mie mi-a plăcut.

„Ei bine, o mică adăugare: clasa SoftReference are două metode. Metoda get() returnează obiectul la care face referire SoftReference . Dacă obiectul a fost șters de către colectorul de gunoi, metoda get () va începe brusc să returneze nul.”

„Utilizatorul poate șterge SoftReference în mod explicit apelând metoda clear(). În acest caz, legătura slabă din interiorul obiectului SoftReference va fi distrusă.”

"Asta este tot pentru acum."

— Mulțumesc pentru povestea interesantă, Ellie. Chiar a fost foarte interesant.