Muistinhallinta sisään Java

⚡ Älykäs yhteenveto

Muistinhallinta sisään Java selittää, miten JVM jakaa ajonaikaisen muistin pinon, keon ja Codeja staattiset alueet, miten objektiviittaukset kulkevat metodikutsujen aikana ja miten roskienkerääjä palauttaa tavoittamattomat objektit, jotta sovellukset pysyvät vakaina ja muistivuotoilta suojattuina.

  • 🧠 JVM-muistin asettelu: Java Muisti on jaettu Heapiin objekteille, Stackiin metodikehyksille ja paikallisille muuttujille sekä erillisiin alueisiin tavukoodille ja staattiselle datalle.
  • 📚 Pino vs. keko: Pinokehykset noudattavat viimeiseksi-sisään-ensimmäiseksi-ulos-järjestystä ja tallentavat primitiivit ja viittaukset, kun taas keko sisältää kaikki new-operaattorilla luodut objektit.
  • ♻️ Roskakokoelma: Roskienkerääjä tracks saavutettavuutta referenssiketjujen kautta ja vapauttaa automaattisesti muistia objekteilta, joihin mikään säie ei pääse käsiksi.
  • Nykyaikaiset keräilijät: Tuotantotyökuormat perustuvat yhä enemmän G1:een, ZGC:hen ja Shenandoahiin usean gigatavun kokoisten keojen lyhytkestoisessa tiedonkeruussa.
  • 🧪 Käytännön esimerkki: Vaiheittainen Opiskelija-luokan läpikäynti näyttää, milloin viittaukset kelpaavat kerättäväksi ja miten viittausten nollaaminen vapauttaa pohjana olevan objektin.

Muistinhallinta sisään Java

Mitä pinomuisti on? Java?

Pinoa muistia sisään Java on JVM-muistin alue, joka tallentaa metodikehykset, paikalliset muuttujat ja viitemuuttujat kullekin säikeelle. Pinoa käytetään aina järjestyksessä Viimeinen sisään, ensimmäinen ulos, joten viimeksi kutsuttu metodi on päällimmäisenä ja sen paikalliset muuttujat lisätään ja poistetaan kehyksen mukana.

Jokainen säie Java Virtuaalikone saa oman pinomuistinsa, joka pitää metodikutsuja erillään ja säikeiden suojaamina. Primitiiviset lokaalit, kuten int, boolean ja double, sijaitsevat suoraan kehyksen sisällä, kun taas pinomuistissa olevat objektiviittaukset osoittavat kekoon allokoituihin objekteihin.

Mikä on kekomuisti? Java?

Kekomuisti on jaettu JVM-alue, joka sisältää kaikki Java new-operaattorilla luotu objekti ja taulukko sekä kaikki näihin objekteihin kuuluvat viittausmuuttujat instanssikenttinä. Toisin kuin pino, keko jaetaan kaikkien säikeiden kesken, minkä vuoksi objektien käyttö vaatii usein synkronointia.

Keo on roskakeräimen hallinnoima alue. Nykyaikaiset HotSpot-JVM:t jakavat keon lyhytikäisille objekteille tarkoitettuun nuoreen sukupolveen ja pitkäikäisille objekteille tarkoitettuun vanhaan sukupolveen, joiden luokan metatiedot tallennetaan erilliseen natiiviin alueeseen nimeltä Metaspace.

Muistin varaus sisään Java

Muistin varaus sisään Java on prosessi, jossa JVM varaa virtuaalimuistialueita muuttujille ja luokkien ja rakenteiden instansseille ohjelman suorituksen aikana. Muistia ei allokoida objektille määrittelyn yhteydessä; vain viittaus luodaan. Varsinainen objektien allokointi tapahtuu new-operaattorin kautta, joten jokainen objekti sijaitsee keossa (Heap).

Java muistin allokointi on jaettu seuraaviin osiin:

  1. pino
  2. Pinota
  3. Code
  4. Staattinen

Tämä muistin jako on välttämätön ajonaikaisen ympäristön tehokkaalle hallinnalle.

  • Code osio sisältää käännetyn tavukoodi.
  • Pinota osastokaupat metodit, paikalliset muuttujat ja viitemuuttujat.
  • pino jakso sisältää esineet ja voi sisältää myös instanssikenttinä säilytettyjä viitemuuttujia.
  • Staattinen osio pitää staattinen data ja staattiset menetelmät jaettu kaikissa instansseissa.

Ero paikallisen ja ilmentymämuuttujan välillä

Ymmärtämällä, missä kukin muuttujatyyppi sijaitsee JVM:ssä, voidaan selittää pinoamisen ja keon toimintaa. esiintymän muuttuja ilmoitetaan luokan sisällä, mutta minkä tahansa metodin ulkopuolella, ja se elää Keossa osana kohdetta.

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

A paikallinen muuttuja ilmoitetaan metodin sisällä, mukaan lukien metodiargumentit, ja sijaitsee Stackissa aktiivisen kehyksen sisällä.

public void sum(int a){

int x = a + 3;

// a, x are local variables

}

Ero pinon ja kasan välillä

Stack ja Heap ratkaisevat erilaisia ​​ongelmia JVM:n sisällä. Stack antaa jokaiselle säikeelle nopean ja deterministisen allokoinnin lyhytikäiselle datalle, joka on sidottu metodin laajuuteen, kun taas Heap tarjoaa jaetun alueen pitkäikäisille objekteille, joihin mikä tahansa säie voi viitata. Alla oleva lyhyt video tiivistää eron ennen seuraavaa läpikäyntiä.

Napauta täältä jos video ei ole saatavilla

Nähdäksesi, miten Stack ja Heap toimivat yhdessä, tarkastellaan päämetodia, joka kutsuu metodia m1.

public void m1{
int x = 20;
}

JVM-pinossa luodaan kehys metodille m1.

Java Pino ja kasa

Muuttuja x luodaan myös muuttujassa m1 pinossa olevaan muuttujan m1 kehykseen, kuten alla olevassa kuvassa näkyy.

Java Pino ja kasa

Metodi m1 kutsuu sitten metodia m2. Pinossa luodaan uusi kehys metodille m2 metodin m1 kehyksen päälle.

Java Pino ja kasa

Java Pino ja kasa

Myös paikalliset muuttujat b ja c luodaan pinossa olevan m2-kehyksen sisälle.

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

Seuraavaksi m2 kutsuu metodia m3. Jälleen pinon päälle luodaan kehys m3:lle, kuten alla on esitetty.

Java Pino ja kasa

Java Pino ja kasa

Oletetaan nyt, että metodi m3 luo objektin luokalle Account, jolla on kaksi instanssimuuttujat int p ja int q.

class Account {
    int p;
    int q;
}

Tässä on koodi metodille m3.

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

Lause new Account() luo Account-objektin kekoon.

Java Pino ja kasa

Viitemuuttuja ref luodaan pinoon m3:n kehyksen sisälle.

Java Pino ja kasa

Sijoitusoperaattori asettaa viittausmuuttujan osoittamaan keon objektiin.

Java Pino ja kasa

Kun metodi on suoritettu loppuun, ohjaus palaa kutsuvalle metodille, joka tässä tapauksessa on metodi m2.

Java Pino ja kasa

Metodin m3 kehys tyhjennetään pinosta.

Java Pino ja kasa

Koska viitemuuttuja ei enää osoita keossa olevaan objektiin, kyseisestä objektista tulee roskienkeruukelpoinen.

Java Pino ja kasa

Kun metodi m2 on valmis, se poistetaan pinosta ja kaikki sen muuttujat poistuvat käytöstä. Sama tapahtuu metodille m1, ja lopulta ohjaus palaa päämetodiin.

Entä jos objektilla on toinen viittaus instanssimuuttujana?

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;
}

Tässä tapauksessa referenssimuuttujalapsi sijaitsee Heap-muistissa osana A-objektia ja osoittaa puolestaan ​​omaan B-objektiinsa, kuten alla on esitetty.

Java Pino ja kasa

Mitä roskakeräys sisältää Java?

Roskakeräys sisään Java on prosessi, jolla JVM suorittaa muistinhallinnan automaattisesti. Roskienkerääjä löytää objektit, joihin ei enää saada yhteyttä mistään reaaliaikaisesta viittauksesta, ja vapauttaa niiden muistin. Dynaaminen muistin allokointi tapahtuu new-operaattorin avulla, ja muisti pysyy allokoituna, kunnes ohjelmalla ei enää ole viittauksia objektiin.

Kun viittauksia ei ole jäljellä, objektia ei enää pidetä tarpeellisena, ja sen käyttämä muisti voidaan vapauttaa. Objektia ei tarvitse tuhota erikseen, koska Java käsittelee kauppojen allokoinnin automaattisesti roskienkerääjän kautta.

Tämän taustalla oleva tekniikka tunnetaan ns. RoskakokoelmaOhjelmat, jotka eivät pysty vapauttamaan muistia, kaatuvat lopulta, kun mitään ei ole enää varattavaa. Tällaisten ohjelmien sanotaan omaavan muisti vuotaa. Roskakeräys sisään Java toimii automaattisesti ohjelman koko elinkaaren ajan, mikä poistaa manuaalisen allokoinnin taakan ja vähentää vuotojen riskiä.

C-kielessä ohjelmoija on puolestaan ​​vastuussa dynaamisesti allokoidun muistin vapauttamisesta free()-funktion avulla. Tässä kohtaa Java muistinhallinta tarjoaa vahvan edun.

Nykyaikaisissa HotSpot-JVM-koneissa on useita roskankerääjiä, jotka on viritetty erilaisille työkuormille. Oletusarvoinen G1-roskankerääjä pyrkii tasapainottamaan läpimenoajan ja taukoajat usean gigatavun kokoisilla keoilla. ZGC ja Shenandoah pyrkivät millisekunnin alle kestäviin taukoihin erittäin suurilla keoilla, mikä tekee niistä...traclatenssiherkille palveluille. Oikean keräilijän valitseminen ja nuoren sukupolven, vanhan sukupolven ja metatilan kokojen säätäminen on ydinosaamista Java esitystyö.

Huomautus: Kaikki objektit luodaan muistin Heap-osioon, joka on roskienkerääjän hallinnoima alue.

Esimerkki: Roskienkeräysmekanismin oppiminen Java

Tämä ohje näyttää, milloin viittaukset kelpaavat roskienkeruuseen yksinkertaisen ohjelman sisällä.

Vaihe 1) Kopioi seuraava koodi editoriin.

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();
  }
}

Vaihe 2) Tallenna, käännä ja suorita koodi. Kuten kaaviossa näkyy, luodaan kaksi objektia ja kaksi viitemuuttujaa.

 Jätteenkeräysmekanismi

Vaihe 3) Poista kommentit riveiltä 20, 21 ja 22. Tallenna, käännä ja suorita koodi.

Vaihe 4) Kuten alla olevassa kaaviossa näkyy, kaksi viitemuuttujaa osoittavat nyt samaan objektiin.

Jätteenkeräysmekanismi

Vaihe 5) Poista kommentit riveiltä 23 ja 24. Tallenna, käännä ja suorita koodi.

Vaihe 6) Kuten alla on esitetty, s2 muuttuu nulliksi, mutta s3 osoittaa edelleen objektiin, joten objekti ei ole vielä oikeutettu roskienkeruuseen.

 Jätteenkeräysmekanismi

Vaihe 7) Poista kommentit riveiltä 25 ja 26. Tallenna, käännä ja suorita koodi.

Vaihe 8) Tässä vaiheessa objektiin ei enää osoita viittauksia, joten se soveltuu roskakorjaukseen. Roskakorjain poistaa sen muistista, eikä sitä voida enää palauttaa.

 Opi roskienkerääjä

Objektin poistaminen Java?

Java ei tarjoa manuaalista poisto-operaattoria, joten vakiotapana on poistaa kaikki viittaukset objektiin, jotta roskienkerääjä voi ottaa sen takaisin.

1) Jotta objektista voi tehdä roskienkeruukelpoisen, aseta jokainen siihen osoittava viitemuuttuja arvoon null.

2) Primitiivityypit eivät ole olioita, joten niille ei voida antaa null-arvoa. Niiden tallennustila vapautetaan automaattisesti, kun ympäröivä Stack-kehys avataan.

Kuinka poistaa esine Java

UKK

Stack tallentaa metodikehykset, paikalliset muuttujat ja viittaukset järjestyksessä Viimeinen sisään, Ensimmäinen ulos säikeittäin. Heap tallentaa kaikki new-metodilla luodut objektit ja se jaetaan säikeiden kesken, minkä vuoksi roskienkerääjä hallinnoi sitä.

Roskienkerääjä kävelee läpi viittausketjuja GC-juurista, kuten aktiivisista säikeistä ja staattisista kentistä. Kaikki objektit, joihin ei päästä juuresta, katsotaan saavuttamattomiksi ja ne voidaan palauttaa seuraavan keräysjakson aikana.

Nuori sukupolvi sisältää lyhytikäisiä objekteja Eden- ja Survivor-tiloissa. Vanha sukupolvi sisältää objekteja, jotka säilyvät useissa kokoelmissa. Metatila on natiivimuistialue, joka tallentaa luokan metatiedot ja korvasi vanhemman PermGenin Java 8.

G1 on oletusarvo ja sopii useimmille työkuormille usean gigatavun keoilla. ZGC ja Shenandoah kohdistavat millisekunnin alle keskeytykset erittäin suurissa keoissa ja ovat hyviä valintoja viiveherkille palveluille, jotka toimivat Java 17 tai uudempi.

Aseta jokainen objektiin osoittava viittaus tyhjäksi tai anna viittausten pudota soveltamisalan ulkopuolelle, kun niiden pinokehykset poistetaan. Kun objektiin ei enää saavuta aktiivista viittausta, roskankerääjä vapauttaa kekomuistinsa.

Kyllä. Tekoälypohjaiset viritystyökalut analysoivat GC-lokeja, allokointinopeuksia ja keskeyttävät histogrammeja suositellakseen kekokoja, keräilijän lippuja ja nuorten sukupolvien suhteita. Ne lyhentävät takaisinkytkentäsilmukkaa manuaaliseen viritykseen verrattuna, erityisesti G1-, ZGC- ja Shenandoah-työkuormissa.

Tekoälypohjaiset havainnointialustat käsittelevät heap dump -tiedostoja ja reaaliaikaisia ​​mittareita ja ryhmittelevät sitten säilytettyjen objektien graafit merkitäkseen epäilyttävät luokat ja viiteketjut. Tämä löytää vuotoehdokkaita nopeammin kuin manuaalinen heap-analyysi ja auttaa tiimejä paikantamaan perimmäisen syyn tuotannossa.

Tiivistä tämä viesti seuraavasti: