Gestionarea gratuită a memoriei companiei în legăturile slabe și ușoare ale java

Colectarea de gunoi în limbile moderne este concepută pentru a salva programatorul de la grijile asociate gestionării memoriei. În acest articol, vom examina două cazuri de gestionare a eliberării automate a memoriei.







Desigur, în realitate, totul este mai complicat: obiectele sunt împărțite în generații, se folosește mecanismul de "dumping card" și altele. Dar pentru scopurile noastre, această schemă conceptuală este suficientă:

Gestionarea gratuită a memoriei companiei în legăturile slabe și ușoare ale java

Aceste link-uri care sunt prezentate în această imagine sunt normale. Ele se formează atunci când obiectului i se atribuie o variabilă:

Pentru anumite sarcini, această abordare poate părea prea inflexibilă.

Poate că, uneori, este logic să salvați un obiect, chiar dacă există referințe la el? Sau din contră - pentru a elimina, chiar dacă este accesibil din setul rădăcină? Sau, poate, unele obiecte are sens să nu distrugă imediat, dar să facă niște acțiuni înainte de distrugere?

Sarcina 1: dispariția cutiilor

O mulțime de cutii au ajuns în depozitul dvs. și trebuie să atribuiți câte un număr fiecărei cutii. În acest scop, este introdusă o placă de tip hash, în care cheile sunt legături la casete, iar valorile sunt numerele lor. Aproximativ astfel:

La intrarea în depozit, caseta este adăugată la tabel:

Acest lucru ridică o problemă: atunci când o cutie este expediată dintr-un depozit, memoria alocată pentru aceasta nu este lansată, deoarece tabela hash conține o legătură cu caseta și mașina virtuală consideră că este "în viață".

Întrebare: Cum pot modifica o tabelă de tip hash astfel încât memoria să se elibereze după expedierea casetei?

O posibilă soluție:

Această sarcină este una dintre variantele unei probleme destul de generale: există un obiect cu o durată de viață "medie" (adică trăiește mai mult decât metoda care a alocat memoria pentru ea, dar mai puțin decât aplicația), acest obiect este asociat cu metadatele și acest link este stocat în dicționar. Ca rezultat, este necesar ca un anumit punct să fie necesar pentru a curăța dicționarul de înregistrări inutile. Dacă acest al treilea obiect uită accidental să curețe dicționarul, va exista o scurgere de memorie.







Ar fi frumos ca intrările din acest dicționar să nu fie luate în considerare la calcularea accesibilității obiectului - adică dacă colectorul de gunoi a distrus obiectul cutiei. când link-uri către el au fost lăsate numai în dicționar.

Link-urile slabe sunt create astfel:

În cazul în care obiectul boxRef rămâne singura referință live la obiectul cutie. obiectul caseta va fi șters de colectorul de gunoi:

Gestionarea gratuită a memoriei companiei în legăturile slabe și ușoare ale java

Să ne întoarcem la exemplul nostru: dacă adăugați un obiect "cutie" la o legătură slabă atunci când adăugați o intrare la tabela hash, aceasta rezolvă problema pierderilor de memorie. Cu toate acestea, aceasta va crea o altă problemă: să se ocupe de o tabelă de tip hash, cheia în intrarea în care se poate transforma în mod neașteptat în nulă - ocupația nu este cea mai plăcută. De aceea, tabelul nostru ar trebui să fie suficient de inteligent pentru a șterge înregistrarea în sine imediat ce obiectul la care se referă cheia este șters.

Punerea în aplicare a unui astfel de tabel este foarte interesantă, dar într-o oarecare măsură depășește sfera acestei note. Vom folosi clasa standard WeakHashMap. O posibilă implementare poate fi găsită în Apache Harmony, care a venit ca o bibliotecă de clasă pe Android.

Sarcina 2: Calea corectă pentru OutOfMemoryError

Trebuie să convertiți câteva (sute de mii) de imagini. Pentru aceasta, aveți acest cod:

Ideea de prealocare a unui tampon pentru un fișier pare normală: alocarea memoriei de fiecare dată pentru fiecare imagine nouă poate încetini puțin aplicația. Cu toate acestea, există o nouă problemă: dintr-o dată, aplicația nu va mai avea suficientă memorie? Apoi, probabil, este rezonabil să neglijați tamponul și să returnați memoria în sistem.

Întrebare: Cum pot modifica codul astfel încât aplicația să păstreze tamponul, dacă memoria este suficientă și să o elibereze dacă memoria din sistem se termină?

O posibilă soluție

Aici avem nevoie de un comportament care este inversul comportamentului legăturilor slabe. Vrem să specificăm colectorului de gunoi că un anumit tip de obiecte ar trebui să fie păstrate în memorie cât mai mult timp posibil, fără a risca să obțină OutOfMemoryError.

Acest lucru se poate realiza cu ajutorul "legăturilor moi". Acestea funcționează după cum urmează: dacă un obiect este accesibil printr-un set de linkuri moi (ușor accesibil, vezi figura), atunci mașina virtuală va încerca să păstreze acest obiect în memorie cât mai mult posibil.

Gestionarea gratuită a memoriei companiei în legăturile slabe și ușoare ale java

Tot ceea ce este necesar în sarcina noastră este de a împacheta tamponul într-o legătură moale.

Astfel, legăturile moi oferă ceva de genul caching. Dar asta, desigur, nu este caching-ul real. Dacă aplicația dvs. are nevoie de o memorie cache completă, atunci există doar câteva linkuri moi, trebuie să implementați strategiile de caching, dacă este posibil, independent de cantitatea de memorie liberă. Prin urmare, legăturile moi sunt uneori numite "cache pentru cei săraci".







Trimiteți-le prietenilor: