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.

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:
- pino
- Pinota
- Code
- 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.
Muuttuja x luodaan myös muuttujassa m1 pinossa olevaan muuttujan m1 kehykseen, kuten alla olevassa kuvassa näkyy.
Metodi m1 kutsuu sitten metodia m2. Pinossa luodaan uusi kehys metodille m2 metodin m1 kehyksen päälle.
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.
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.
Viitemuuttuja ref luodaan pinoon m3:n kehyksen sisälle.
Sijoitusoperaattori asettaa viittausmuuttujan osoittamaan keon objektiin.
Kun metodi on suoritettu loppuun, ohjaus palaa kutsuvalle metodille, joka tässä tapauksessa on metodi m2.
Metodin m3 kehys tyhjennetään pinosta.
Koska viitemuuttuja ei enää osoita keossa olevaan objektiin, kyseisestä objektista tulee roskienkeruukelpoinen.
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.
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.
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.
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.
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.
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.


















