Toate obiectele create în cadrul maşinii virtuale pe parcursul rulării unui program sunt plasate în zona de memorie numită Heap. Ştergerea acestora din memorie este realizată automat de către o componentă a JVM numita Garbage Collector. Acest proces şterge din zona Heap toate obiectele care nu mai sunt referite în cadrul programului aflat în execuţie.
Mecanismul Garbage Collector de eliberare a memorie de obiecte care nu mai sun folositoare oferă două avantaje importante. În primul rând programatorul nu trebuie sa se îngrijească în mod explicit de eliberarea obiectelor nefolositoare. Datorită unor erori de implementare care duc la situaţii de supraîncărcare a memorie programatorul poate să îşi piardă multe ore pentru a găsi şi repara defectul. Un al doilea avantaj este acela că GC asigură integritatea programelor – nu permite ştergerea accidentală a unor obiecte sau zone de memorie care ar duce pierderea integrităţii programului sau a maşinii virtuale.
Încărcare suplimentară a procesorului dată de componenta GC este un dezavantaj al acestei abordări de eliberare automate a memoriei. Această problemă este rezolvată într-o măsură destul de mare prin dezvoltarea unor algoritmi performanţi implementaţi la nivelul GC.
Este important de reţinut faptul că, nu poate fi prezis in avans momentul în care un obiect urmează să fie eliberat din memorie. Programatorul nu trebuie să îşi bazeze arhitectura programului plecând de la anumite presupuneri asupra momentului în care un anumit obiect va fi eliberat din memorie.
IMPORTANT Deşi mecanismul GC asigură eliberarea memorie de obiectele care nu mai sunt referite, există pericolul ca un program prost gândit şi implementat să aibă probleme de alocare a memorie, şi să se ajungă la situaţia de depăşire a memorie – fapt care duce la întreruperea programului. Acest lucru se poate întâmpla deoarece GC şterge din zona Heap doar acele obiecte care nu sunt referite de către nici o variabila.
Deşi nu se poate şti în avans exact momentul în care un obiect este eliberat din memorie, obiectele care urmează să fie şterse sunt anunţate prin apelarea metodei finalize(). Metoda finalize() se regăseşte în cadrul oricărui obiect java (fiind moştenită din cadrul clasei de bază Object) şi este apelată de către GC în momentul în care obiectul urmează să fie şters.
package mihai.java.intro.gc; public class GarbageCollectorTest { static int removedObjects; public static class Flower{ String name; Flower(String name){ this.name = name; } public void finalize(){ removedObjects++; System.err.println("The flower "+name+" is removed. Number of removed flowers is "+removedObjects); } } public static void main(String[] args) { Flower myF = null; int i = 0; while(true){ i++; myF = new Flower(" Flower "+i); } } }
În listingul anterior este prezentat un program care demonstrează faptul că la eliberarea fiecărui obiect din memorie este apelată metoda finalize() a acestuia. Rezultatul executiei programului este urmatorul:
The flower Flower 482312 is removed. Number of removed flowers is 2974 The flower Flower 482311 is removed. Number of removed flowers is 2975 The flower Flower 482310 is removed. Number of removed flowers is 2976 The flower Flower 482309 is removed. Number of removed flowers is 2977 The flower Flower 482308 is removed. Number of removed flowers is 2978 The flower Flower 482307 is removed. Number of removed flowers is 2979 The flower Flower 482306 is removed. Number of removed flowers is 2980 The flower Flower 482305 is removed. Number of removed flowers is 2981 The flower Flower 482304 is removed. Number of removed flowers is 2982
Se observa ca, desi, in cadrul programului nu am apelat in mod explicit functia finalize(), pe ecran este afisat mesajul The flower X is removed…. Acest mesaj este afisat de fiecare data cand metoda finalized() este apelata pentru un obiect ce urmeaza a fi sters din memorie de catre garbage collector.
Intrarea în acţiune a GC şi eliberarea memoriei de obiecte (deci implicit apelarea metodei finalize()) nu este garantată de către maşina virtuală java. Ca urmare a acestui fapt, toate operaţiile de eliberarea de resurse care trebuiesc realizate în cadrul unei aplicaţii (de exemplu închiderea unor conexiuni de reţea, unor fişiere, închiderea unor conexiuni la baze de date, etc.) trebuie să fie realizate de programator în mod manual prin construirea unor metode care sunt apelate în mod explicit la momentul potrivit.