Lucrul cu generații de obiecte

Colectatorii de gunoi Java implementează o strategie generațională de colectare a gunoiului care poate clasifica obiectele după vârstă.

O astfel de nevoie (de a marca și compacta toate obiectele) în JVM poate fi numită ineficientă. Deoarece pe măsură ce se alocă un număr mare de obiecte, lista acestora crește, ceea ce duce la o creștere a timpului de colectare a gunoiului. Analiza empirică a aplicațiilor a arătat că majoritatea obiectelor din Java sunt de scurtă durată.

Zona de memorie heap din JVM este împărțită în trei secțiuni:

Lucrul cu generații de obiecte

Generația tânără

Obiectele nou create încep în generația tânără. Generația tânără este în continuare împărțită în două categorii.

  • Eden Space - Toate obiectele noi încep aici, le este alocată memoria inițială.
  • Survivor Spaces (FromSpace și ToSpace) - Obiectele sunt mutate aici din Eden după ce au supraviețuit unui ciclu de colectare a gunoiului.

Procesul în care obiectele sunt colectate gunoi de la generația mai tânără se numește un eveniment minor de colectare a gunoiului.

Când spațiul lui Eden este umplut cu obiecte, se face o mică colectare a gunoiului. Toate obiectele moarte sunt îndepărtate și toate cele vii sunt mutate într-unul dintre cele două spații rămase. Micul GC verifică și obiectele din spațiul supraviețuitorului și le mută în alt spațiu (următorul) supraviețuitor.

Să luăm ca exemplu următoarea secvență.

  1. Există obiecte de ambele tipuri (vii și moarte) în Eden.
  2. Are loc un mic GC - toate obiectele moarte sunt îndepărtate din Eden. Toate obiectele vii sunt mutate în spațiu-1 (FromSpace). Edenul și spațiul-2 sunt acum goale.
  3. Sunt create obiecte noi și adăugate în Eden. Unele obiecte din Eden și spațiu-1 devin moarte.
  4. Are loc un mic GC - toate obiectele moarte sunt îndepărtate din Eden și spațiu-1. Toate obiectele vii sunt mutate în spațiu-2 (ToSpace). Edenul și spațiul-1 sunt goale.

Astfel, în orice moment, unul dintre spațiile supraviețuitorilor este întotdeauna gol. Când supraviețuitorii ating un anumit prag de deplasare prin spațiile supraviețuitorilor, ei avansează la o generație mai în vârstă.

Puteți utiliza steag-ul -Xmn pentru a seta dimensiunea generației tinere .

Generația mai veche

Obiectele care trăiesc o perioadă semnificativă de timp (de exemplu, cea mai mare parte a duratei de viață a unui program) devin în cele din urmă obiecte mai vechi - centenare. Este cunoscută și ca generația obișnuită și conține obiecte care au fost lăsate mult timp în Survivor Spaces.

Pragul de viață al unui obiect determină câte cicluri de colectare a gunoiului trebuie să treacă înainte de a fi mutat la generația mai veche. Procesul în care obiectele sunt trimise la gunoi din generația mai veche se numește evenimentul principal de colectare a gunoiului.

Puteți utiliza steagurile -Xms și -Xmx pentru a seta dimensiunea inițială și maximă a memoriei heap .

Deoarece Java folosește colectarea de gunoi generațională, cu cât un obiect experimentează mai multe evenimente de colectare a gunoiului, cu atât se deplasează mai departe pe heap. El începe în generația mai tânără și în cele din urmă ajunge în generația obișnuită dacă trăiește suficient.

Pentru a înțelege promovarea obiectelor între spații și generații, luați în considerare următorul exemplu:

Când un obiect este creat, acesta este mai întâi plasat în spațiul Eden al tinerei generații.

De îndată ce are loc o mică colectare a gunoiului, obiectele vii din Eden sunt mutate în FromSpace. Când are loc următoarea colectare minoră a gunoiului, obiectele vii din Eden și spațiu sunt mutate în ToSpace.

Acest ciclu continuă de un anumit număr de ori. Dacă obiectul este încă „în serviciu” după acest punct, următorul ciclu de colectare a gunoiului îl va muta în spațiul de generație mai veche.

Generație permanentă și metaspațiu

Metadatele precum clasele și metodele sunt stocate în generare persistentă. JVM-ul îl populează în timpul rulării pe baza claselor utilizate de aplicație. Clasele care nu mai sunt folosite pot trece de la generație permanentă la gunoi.

Puteți utiliza steagurile -XX:PermGen și -XX:MaxPermGen pentru a seta dimensiunea inițială și maximă a generației permanente .

metaspațiu

De la Java 8, spațiul PermGen a fost înlocuit cu spațiul de memorie MetaSpace. Implementarea diferă de PermGen - acest spațiu heap este acum schimbat automat.

Acest lucru evită problema de lipsă de memorie a aplicației, care apare din cauza dimensiunii limitate a spațiului heap al PermGen. Memoria metaspațială poate fi colectată de gunoi, iar clasele care nu mai sunt utilizate vor fi curățate automat când metaspațiul atinge dimensiunea maximă.