Stivați memoria și spațiul Heap în Java

1. Introducere

Pentru a rula o aplicație într-un mod optim, JVM împarte memoria în memorie stack și heap. Ori de câte ori declarăm noi variabile și obiecte, apelăm o metodă nouă, declarăm un șir sau efectuăm operații similare, JVM desemnează memoria acestor operații fie din Stack Memory, fie din Heap Space.

În acest tutorial, vom discuta despre aceste modele de memorie. Vom enumera câteva diferențe cheie între ele, modul în care sunt stocate în RAM, caracteristicile pe care le oferă și unde să le folosim.

2. Stivați memoria în Java

Stack Memory în Java este utilizat pentru alocarea de memorie statică și pentru executarea unui thread. Conține valori primitive specifice unei metode și referințe la obiecte care se află într-o grămadă, referite din metodă.

Accesul la această memorie este în ordinea Last-In-First-Out (LIFO). Ori de câte ori este apelată o nouă metodă, se creează un bloc nou deasupra stivei care conține valori specifice acelei metode, cum ar fi variabile primitive și referințe la obiecte.

Când metoda termină execuția, cadrul corespunzător al stivei este spălat, fluxul revine la metoda apelantă și spațiul devine disponibil pentru următoarea metodă.

2.1. Caracteristici cheie ale memoriei Stack

În afară de ceea ce am discutat până acum, următoarele sunt câteva alte caracteristici ale memoriei stivei:

  • Crește și se micșorează pe măsură ce sunt apelate și returnate noi metode
  • Variabilele din stivă există numai atât timp cât se execută metoda care le-a creat
  • Este alocat și repartizat automat atunci când metoda termină execuția
  • Dacă această memorie este plină, Java aruncă java.lang.StackOverFlowError
  • Accesul la această memorie este rapid în comparație cu memoria heap
  • Această memorie este sigură pentru fire, deoarece fiecare fir funcționează în propria stivă

3. Spațiu Heap în Java

Spațiul Heap în Java este utilizat pentru alocarea dinamică a memoriei pentru obiecte Java și clase JRE în timpul rulării . Obiectele noi sunt întotdeauna create în spațiul heap și referințele la aceste obiecte sunt stocate în memoria stivei.

Aceste obiecte au acces global și pot fi accesate de oriunde din aplicație.

Acest model de memorie este în continuare împărțit în părți mai mici numite generații, acestea sunt:

  1. Young Generation - aici sunt alocate și îmbătrânite toate obiectele noi. O colectare minoră de gunoi apare atunci când aceasta se umple
  2. Generație veche sau permanentă - aici sunt depozitate obiectele care au supraviețuit mult timp. Când obiectele sunt stocate în generația tânără, se stabilește un prag pentru vârsta obiectului și când este atins pragul, obiectul este mutat în vechea generație
  3. Generare permanentă - aceasta constă din metadate JVM pentru clasele de runtime și metodele de aplicare

Aceste porțiuni diferite sunt, de asemenea, discutate în acest articol - Diferența dintre JVM, JRE și JDK.

Putem oricând să manipulăm dimensiunea memoriei heap conform cerințelor noastre. Pentru mai multe informații, vizitați acest articol Baeldung legat.

3.1. Caracteristici cheie ale memoriei Java Heap

În afară de ceea ce am discutat până acum, sunt prezentate câteva alte caracteristici ale spațiului heap:

  • Este accesat prin tehnici complexe de gestionare a memoriei care includ Young Generation, Old sau Tenured Generation și Permanent Generation
  • Dacă spațiul heap este plin, Java aruncă java.lang.OutOfMemoryError
  • Accesul la această memorie este relativ mai lent decât memoria stivei
  • Această memorie, spre deosebire de stivă, nu este alocată automat. Are nevoie de Garbage Collector pentru a elibera obiectele neutilizate, astfel încât să păstreze eficiența utilizării memoriei
  • Spre deosebire de stivă, un heap nu este sigur pentru fire și trebuie protejat prin sincronizarea corectă a codului

4. Exemplu

Pe baza a ceea ce am învățat până acum, să analizăm un cod Java simplu și să evaluăm modul în care este gestionată memoria aici:

class Person { int id; String name; public Person(int id, String name) { this.id = id; this.name = name; } } public class PersonBuilder { private static Person buildPerson(int id, String name) { return new Person(id, name); } public static void main(String[] args) { int id = 23; String name = "John"; Person person = null; person = buildPerson(id, name); } }

Să analizăm acest pas cu pas:

  1. La introducerea metodei main () , ar fi creat un spațiu în memoria stivei pentru a stoca primitive și referințe ale acestei metode
    • Valoarea primitivă a întreg id va fi stocat direct în memoria stivă
    • Variabila de referință Persoana de tip Persoana va fi creat și în stiva de memorie , care va indica obiectul real în grămadă
  2. Apelul către constructorul parametrizat Person (int, String) de la main () va aloca memorie suplimentară deasupra stivei anterioare. Aceasta va stoca:
    • Această obiectului de referință al obiectului de asteptare din stiva de memorie
    • ID-ul valorii primitive din memoria stivei
    • Variabila de referință a numelui argumentului String, care va indica șirul real din grupul de șiruri din memoria heap
  3. Metoda principală apelează în continuare metoda statică buildPerson () , pentru care va avea loc o alocare suplimentară în memoria stivei, pe lângă cea anterioară. Aceasta va stoca din nou variabilele în modul descris mai sus.
  4. Cu toate acestea, pentru persoana obiect nou creată de tip Person , toate variabilele de instanță vor fi stocate în memoria heap.

Această alocare este explicată în această diagramă:

5. Rezumat

Înainte de a încheia acest articol, să rezumăm rapid diferențele dintre memoria stivă și spațiul Heap:

Parametru Memorie stivă Heap Space
Cerere Stiva este utilizată în părți, una câte una în timpul executării unui fir Întreaga aplicație folosește spațiu Heap în timpul rulării
mărimea Stiva are limite de dimensiune în funcție de sistemul de operare și este de obicei mai mică decât Heap Nu există nicio limită de dimensiune pentru Heap
Depozitare Stochează numai variabile primitive și referințe la obiecte care sunt create în spațiul Heap Toate obiectele nou create sunt stocate aici
Ordin Se accesează utilizând sistemul de alocare a memoriei Last-in First-out (LIFO) Această memorie este accesată prin tehnici complexe de gestionare a memoriei care includ Young Generation, Old sau Tenured Generation și Permanent Generation.
Viaţă Memoria stivă există numai atât timp cât se execută metoda curentă Spațiul Heap există atât timp cât aplicația rulează
Eficienţă Comparativ mult mai rapid de alocat în comparație cu heap Mai lent de alocat în comparație cu stiva
Alocare / Dealocare Această memorie este alocată și repartizată automat atunci când o metodă este apelată și respectiv returnată Spațiul heap este alocat atunci când obiecte noi sunt create și alocate de Gargabe Collector atunci când nu mai sunt referite

6. Concluzie

Stack și heap sunt două moduri în care Java alocă memorie. În acest articol, am înțeles cum funcționează și când să le folosim pentru dezvoltarea unor programe Java mai bune.

Pentru a afla mai multe despre gestionarea memoriei în Java, aruncați o privire la acest articol aici. De asemenea, am discutat despre JVM Garbage Collector, care este discutat pe scurt în acest articol.