Mäluhaldus sisse Java

⚡ Nutikas kokkuvõte

Mäluhaldus sisse Java selgitab, kuidas JVM jagab käitusaja mälu pinu, kuhja ja muu vahel. Codeja staatilisi piirkondi, kuidas objektiviited meetodikõnede ajal voolavad ja kuidas prügikoguja kättesaamatuid objekte taastab, et rakendused püsiksid stabiilsed ja mäluleketeta.

  • 🧠 JVM-i mälu paigutus: Java mälu on jagatud objektide jaoks mõeldud heapiks, meetodiraamide ja kohalike muutujate jaoks mõeldud pinuks ning lisaks eraldi aladeks baitkoodi ja staatiliste andmete jaoks.
  • 📚 Stack vs Heap: Stack-raamid järgivad järjekorda Viimane-Sisse-Esimene-Välja ning salvestavad primitiivid ja viited, samas kui Heap sisaldab kõiki new operaatoriga loodud objekte.
  • ♻️ Prügi kogumine: Prügikoristaja tracks ligipääsetavust viiteahelate kaudu ja taastab automaatselt mälu objektidelt, kuhu ükski lõim ei pääse ligi.
  • Kaasaegsed kollektsionäärid: Tootmiskoormused tuginevad üha enam G1-le, ZGC-le ja Shenandoah'le mitme gigabaidise mahuga kuhjade lühikese pausiga kogumiseks.
  • 🧪 Praktiline näide: Samm-sammult juhend õpilase klassile näitab, millal viited muutuvad kogumiseks sobivaks ja kuidas viidete nullimine vabastab alusobjekti.

Mäluhaldus sisse Java

Mis on pinumälu? Java?

Mälu virn Java on JVM-i mälu piirkond, mis salvestab iga lõime meetodi raame, lokaalseid muutujaid ja viitemuutujaid. Stackile pääseb alati juurde järjekorras viimane-sisene-esimene-välja, seega on viimati käivitatud meetod peal ning selle lokaalsed muutujad lükatakse ja ilmuvad koos kaadriga.

Iga niit selles Java Virtuaalmasin saab oma Stacki, mis hoiab meetodite kutsumised isoleerituna ja lõimekindlalt. Primitiivsed lokaalid, näiteks int, boolean ja double, asuvad otse raami sees, samas kui Stackis talletatud objektiviited osutavad Heapil eraldatud objektidele.

Mis on kuhjamälu? Java?

Heap-mälu on jagatud JVM-i piirkond, mis sisaldab kõiki Java new operaatoriga loodud objekt ja massiiv koos kõigi nende objektidega kaasnevate viitemuutujatega eksemplariväljadena. Erinevalt pinust (Spin) jagatakse Heapi (Heap) kõigi lõimede vahel, mistõttu objektidele juurdepääs nõuab sageli sünkroniseerimist.

Heap on ala, mida prügikoguja haldab. Kaasaegsed HotSpot JVM-id jagavad Heapi lühikese elueaga objektide jaoks mõeldud nooreks põlvkonnaks ja pika elueaga objektide jaoks vanaks põlvkonnaks, kusjuures klassi metaandmed salvestatakse eraldi natiivsesse piirkonda nimega Metaspace.

Mälu eraldamine sisse Java

Mälu eraldamine sisse Java on protsess, mille käigus JVM eraldab programmi täitmise ajal virtuaalmälu piirkonnad muutujate ja klasside ning struktuuride eksemplaride jaoks. Mälu ei eraldata objektile deklareerimisel; luuakse ainult viide. Tegelik objekti eraldamine toimub uue operaatori kaudu, seega asub iga objekt heapis.

. Java Mälu eraldamine on jagatud järgmisteks osadeks:

  1. hunnik
  2. Stack
  3. Code
  4. Staatiline

See mälujaotus on vajalik käituskeskkonna tõhusaks haldamiseks.

  • . Code jaotis sisaldab teie kompileeritud baitkood.
  • . Stack osakonna kauplused meetodid, lokaalsed muutujad ja võrdlusmuutujad.
  • . hunnik jaotis sisaldab esemeid ja võib sisaldada ka viitemuutujaid, mida hoitakse eksemplariväljadena.
  • . Staatiline sektsiooni hoidmised staatilised andmed ja staatilised meetodid jagatud kõigis eksemplarides.

Erinevus kohaliku ja eksemplari muutuja vahel

Iga muutujatüübi asukoha mõistmine JVM-is aitab selgitada Stacki ja Heapi käitumist. eksemplari muutuja deklareeritakse klassi sees, aga väljaspool mis tahes meetoditja see elab Kuhjal oma objekti osana.

class Student{ 
int num; // num is instance variable 
public void showData{}

A kohalik muutuja deklareeritakse meetodi sees, sealhulgas meetodi argumendidja asub aktiivse raami sees olevas Stackis.

public void sum(int a){

int x = a + 3;

// a, x are local variables

}

Erinevus virna ja kuhja vahel

Stack ja Heap lahendavad JVM-is erinevaid probleeme. Stack annab igale lõimele kiire ja deterministliku jaotuse lühiajaliste andmete jaoks, mis on seotud meetodi ulatusega, samas kui Heap pakub jagatud piirkonda pikaajaliste objektide jaoks, millele iga lõim saab viidata. Allolev lühike video võtab kokku erinevused enne järgnevat läbimängu.

Click siin kui video pole juurdepääsetav

Stacki ja Heapi koostöö nägemiseks vaatleme peameetodit, mis kutsub esile meetodi m1.

public void m1{
int x = 20;
}

JVM Stackis luuakse meetodi m1 jaoks raam.

Java Virna ja kuhja

Muutuja x muutujas x luuakse ka muutuja m1 raamis pinus, nagu on näidatud alloleval pildil.

Java Virna ja kuhja

Seejärel kutsub meetod m1 välja meetodi m2. Stackis luuakse m2 jaoks uus kaader m1 kaadri peale.

Java Virna ja kuhja

Java Virna ja kuhja

Kohalikud muutujad b ja c luuakse ka pinu m2 raami sees.

public void m2(int b){
boolean c;
}

Järgmisena kutsub m2 välja meetodi m3. Jällegi luuakse pinu peale m3 jaoks raam, nagu allpool näidatud.

Java Virna ja kuhja

Java Virna ja kuhja

Oletame nüüd, et meetod m3 loob objekti klassile Account, millel on kaks eksemplari muutujad int p ja int q.

class Account {
    int p;
    int q;
}

Siin on meetodi m3 kood.

public void m3(){
    Account ref = new Account();
    // more code
}

Lause new Account() loob heapisse Account objekti.

Java Virna ja kuhja

Viitemuutuja ref luuakse m3 jaoks raami sees olevas pinus.

Java Virna ja kuhja

Omistusoperaator paneb viitemuutuja osutama heapil olevale objektile.

Java Virna ja kuhja

Kui meetod on täitmise lõpetanud, naaseb juhtimine kutsuva meetodi juurde, milleks antud juhul on meetod m2.

Java Virna ja kuhja

Meetodi m3 raam tühjendatakse pinust.

Java Virna ja kuhja

Kuna viitemuutuja ei osuta enam heapil olevale objektile, muutub see objekt prügikoristuseks kõlblikuks.

Java Virna ja kuhja

Kui meetod m2 on lõppenud, eemaldatakse see pinust ja kõik selle muutujad muutuvad kättesaamatuks. Sama juhtub meetodi m1 puhul ja lõpuks naaseb juhtimine põhimeetodi juurde.

Mis saab siis, kui objekti eksemplarimuutujana on mõni muu viide?

public static void main(String args[]) {
    A parent = new A();
    // more code
}
class A {
    B child = new B();
    int e;
}
class B {
    int c;
    int d;
}

Sel juhul asub viitemuutuja laps heapil A-objekti osana ja osutab omakorda omaenda B-objektile, nagu allpool näidatud.

Java Virna ja kuhja

Mis on prügikoristus Java?

Prügi kogumine sisse Java on protsess, mille käigus JVM teostab automaatselt mäluhaldust. Prügikoguja leiab objektid, mis pole enam ühegi reaalajas viite kaudu kättesaadavad, ja vabastab nende mälu. Dünaamiline mälu eraldamine toimub uue operaatori kaudu ja mälu jääb eraldatuks seni, kuni programmil pole enam objektile ühtegi viidet.

Kui viiteid enam ei ole, loetakse objekti enam mittevajalikuks ja selle poolt hõivatud mälu saab taastada. Objekti hävitamiseks pole otsest vajadust, sest Java tegeleb tehingute jaotamisega automaatselt prügikoguja kaudu.

Selle taga olev tehnika on tuntud kui PrügikoguProgrammid, mis ei suuda mälu vabastada, jooksevad lõpuks kokku, kui midagi enam eraldada ei jää. Selliste programmide kohta öeldakse, et neil on mälu lekib. Prügi kogumine sisse Java töötab automaatselt kogu programmi eluea jooksul, mis kõrvaldab käsitsi tehingute jaotamise koormuse ja vähendab lekete ohtu.

C-keeles seevastu vastutab programmeerija dünaamiliselt free() funktsiooni kaudu eraldatud mälu vabastamise eest. Siin on koht, kus Java mäluhaldus pakub tugevat eelist.

Kaasaegsed HotSpot JVM-id on varustatud mitme prügikogujaga, mis on häälestatud erinevate töökoormuste jaoks. Vaikimisi G1 prügikoguja eesmärk on tasakaalustatud läbilaskevõime ja pausiajad mitme gigabaidiste kuhjade puhul. ZGC ja Shenandoah püüavad saavutada millisekundilisi pause väga suurte kuhjade puhul, mis teeb nad ...traclatentsustundlike teenuste jaoks. Õige koguja valimine ja noore põlvkonna, vana põlvkonna ja metaruumi suuruste häälestamine on põhioskus Java etendustöö.

Märge: Kõik objektid luuakse mälu Heap-osas, mis on piirkond, mida prügikoguja haldab.

Näide: Prügikogumismehhanismi õppimiseks Java

See läbivaatus näitab, millal viited lihtsa programmi sees prügikoristuseks sobivad.

Step 1) Kopeerige järgmine kood redaktorisse.

class Student{
int a;
int b;
  public void setData(int c,int d){
    a=c;
    b=d;
  }
  public void showData(){
    System.out.println("Value of a = "+a);
    System.out.println("Value of b = "+b);
  }
  public static void main(String args[]){
    Student s1 = new Student();
    Student s2 = new Student();
    s1.setData(1,2);
    s2.setData(3,4);
    s1.showData();
    s2.showData();
    //Student s3;
    //s3=s2;
    //s3.showData();
    //s2=null;
    //s3.showData();
    //s3=null;
    //s3.showData();
  }
}

Step 2) Salvesta, kompileeri ja käivita kood. Nagu diagrammil näidatud, luuakse kaks objekti ja kaks viitemuutujat.

 Prügi kogumise mehhanism

Step 3) Eemalda kommentaarid ridadelt 20, 21 ja 22. Salvesta, kompileeri ja käivita kood.

Step 4) Nagu alloleval diagrammil näidatud, osutavad kaks viitemuutujat nüüd samale objektile.

Prügi kogumise mehhanism

Step 5) Eemalda kommentaarid ridadelt 23 ja 24. Salvesta, kompileeri ja käivita kood.

Step 6) Nagu allpool näidatud, muutub s2 nulliks, kuid s3 osutab endiselt objektile, seega pole objekt veel prügikoristuseks kõlblik.

 Prügi kogumise mehhanism

Step 7) Eemalda kommentaarid ridadelt 25 ja 26. Salvesta, kompileeri ja käivita kood.

Step 8) Sel hetkel ei osuta objektile enam ükski viide, seega muutub see prügikoristuseks kõlblikuks. Prügikorjaja eemaldab selle mälust ja seda pole enam võimalik taastada.

 Õppige prügikogujat

Kuidas objekti kustutada Java?

Java ei paku käsitsi kustutamise operaatorit, seega on standardmeetodiks eemaldada kõik viited objektile, et prügikoguja saaks selle taastada.

1) Prügikoristuseks sobivaks objektiks määrake iga sellele osutav viitemuutuja väärtuseks null.

2) Primitiivsed tüübid ei ole objektid, seega ei saa neile määrata nullväärtust. Nende salvestusruum vabaneb automaatselt, kui ümbritsev Stack-raam hüpatakse välja.

Kuidas objekti kustutada Java

KKK

Stack salvestab iga lõime jaoks meetodite raame, lokaalseid muutujaid ja viiteid viimasena sisse, esimesena välja järjekorras. Heap salvestab kõik new funktsiooniga loodud objektid ja on lõimede vahel jagatud, mistõttu seda haldab prügikoguja.

Prügikoguja läbib GC juurtest lähtuvaid viiteahelaid, näiteks aktiivseid lõime ja staatilisi väljasid. Kõik objektid, millele juurest ligi ei pääse, loetakse kättesaamatuks ja muutuvad järgmise kogumistsükli ajal taastamiseks kõlblikuks.

Noor põlvkond hoiab lühiajalisi objekte Edeni ja Survivori ruumides. Vana põlvkond hoiab objekte, mis jäävad püsima mitmes kollektsioonis. Metaruum on natiivmälu piirkond, mis salvestab klassi metaandmeid ja asendas vanema PermGeni Java 8.

G1 on vaikeväärtus ja sobib enamiku töökoormuste jaoks mitme gigabaidiste kuhjade puhul. ZGC ja Shenandoah on suunatud millisekundilistele pausidele väga suurte kuhjade puhul ning on head valikud latentsusaja suhtes tundlike teenuste jaoks, mis töötavad Java 17 või uuem.

Määra iga objektile osutav viide nulliks või lase viidetel Stack-kaadrite ilmumisel alast välja langeda. Kui objektini ei jõua ühtegi aktiivset viidet, vabastab prügikoguja oma Heap-mälu.

Jah. Tehisintellektil põhinevad häälestamistööriistad analüüsivad GC logisid, jaotusmäärasid ja peatavad histogramme, et soovitada kuhja suurusi, koguja lippe ja noorte põlvkondade suhteid. Need lühendavad tagasisideahelat võrreldes käsitsi häälestamisega, eriti G1, ZGC ja Shenandoah töökoormuste puhul.

Tehisintellektil põhinevad jälgimisplatvormid sisestavad heap dump'eid ja reaalajas mõõdikuid ning seejärel klasterdavad säilitatud objektide graafikuid, et märgistada kahtlased klassid ja viiteahelad. See tuvastab lekke kandidaadid kiiremini kui käsitsi heap analüüs ja aitab meeskondadel tootmiskeskkonnas algpõhjuse kindlaks teha.

Võta see postitus kokku järgmiselt: