Stak hukommelse og bunkeplads i Java

1. Introduktion

For at køre en applikation på en optimal måde opdeler JVM hukommelse i stack og heap-hukommelse. Når vi erklærer nye variabler og objekter, kalder du ny metode, erklærer en Snor eller udføre lignende operationer, udpeger JVM hukommelse til disse operationer fra enten Stack Memory eller Heap Space.

I denne vejledning diskuterer vi disse hukommelsesmodeller. Vi henter nogle vigtige forskelle mellem dem, hvordan de gemmes i RAM, de funktioner de tilbyder, og hvor de skal bruges.

2. Stak hukommelse i Java

Stack Memory i Java bruges til statisk hukommelsesallokering og udførelse af en tråd. Den indeholder primitive værdier, der er specifikke for en metode og referencer til objekter, der er i en bunke, henvist fra metoden.

Adgang til denne hukommelse er i Last-In-First-Out (LIFO) rækkefølge. Når der kaldes til en ny metode, oprettes der en ny blok oven på stakken, der indeholder værdier, der er specifikke for denne metode, som primitive variabler og referencer til objekter.

Når metoden er færdig med udførelsen, skylles den tilsvarende stabelramme, strømmen går tilbage til kaldemetoden, og der bliver plads til den næste metode.

2.1. Nøglefunktioner i Stack Memory

Bortset fra hvad vi hidtil har diskuteret, er følgende nogle andre funktioner i stack-hukommelse:

  • Den vokser og krymper, efterhånden som nye metoder kaldes og returneres
  • Variabler inde i stakken findes kun, så længe den metode, der oprettede dem, kører
  • Det tildeles automatisk og deallokeres, når metoden er færdig med udførelsen
  • Hvis denne hukommelse er fuld, kaster Java java.lang.StackOverFlowError
  • Adgang til denne hukommelse er hurtig sammenlignet med bunkehukommelse
  • Denne hukommelse er trådsikker, da hver tråd fungerer i sin egen stak

3. Heap Space i Java

Bunkeplads i Java bruges til dynamisk hukommelsesallokering til Java-objekter og JRE-klasser i løbetiden. Nye objekter oprettes altid i dyngerum, og referencerne til disse objekter lagres i stakhukommelsen.

Disse objekter har global adgang og kan tilgås fra hvor som helst i applikationen.

Denne hukommelsesmodel er yderligere opdelt i mindre dele kaldet generationer, disse er:

  1. Ung generation - det er her alle nye objekter tildeles og ældes. En mindre affaldssamling opstår, når denne fyldes op
  2. Gammel eller fastholdt generation - det er her, længe overlevende genstande opbevares. Når objekter gemmes i den unge generation, indstilles en tærskel for objektets alder, og når denne tærskel nås, flyttes objektet til den gamle generation
  3. Permanent generation - dette består af JVM-metadata til runtime-klasser og applikationsmetoder

Disse forskellige dele diskuteres også i denne artikel - Forskellen mellem JVM, JRE og JDK.

Vi kan altid manipulere størrelsen på bunkehukommelse i henhold til vores krav. For mere information, besøg denne linkede Baeldung-artikel.

3.1. Nøglefunktioner i Java Heap Memory

Bortset fra hvad vi hidtil har diskuteret, er følgende nogle andre funktioner i bunkerum:

  • Det er tilgængeligt via komplekse hukommelsesstyringsteknikker, der inkluderer Young Generation, Old eller Tenured Generation og Permanent Generation
  • Hvis bunkepladsen er fuld, kaster Java java.lang.OutOfMemoryError
  • Adgangen til denne hukommelse er relativt langsommere end stakhukommelsen
  • Denne hukommelse, i modsætning til stakken, deallokeres ikke automatisk. Det har brug for Garbage Collector for at frigøre ubrugte objekter for at bevare effektiviteten af ​​hukommelsesforbruget
  • I modsætning til stak er en bunke ikke trådsikker og skal beskyttes ved korrekt synkronisering af koden

4. Eksempel

Baseret på hvad vi hidtil har lært, lad os analysere en simpel Java-kode og lad os vurdere, hvordan hukommelse styres her:

klasse Person {int id; Strengnavn; offentlig person (int id, strengnavn) {this.id = id; dette.navn = navn; }} offentlig klasse PersonBuilder {privat statisk person buildPerson (int id, strengnavn) {returner ny person (id, navn); } offentlig statisk ugyldig hoved (String [] args) {int id = 23; String name = "John"; Person person = null; person = buildPerson (id, navn); }}

Lad os analysere dette trin for trin:

  1. Ved ankomsten til hoved () metode, oprettes der et rum i stakhukommelsen til lagring af primitiver og referencer til denne metode
    • Den primitive værdi af heltal id gemmes direkte i stakhukommelsen
    • Referencevariablen person af typen Person oprettes også i stakhukommelsen, der peger på det faktiske objekt i bunken
  2. Opkaldet til den parametriserede konstruktør Person (int, streng) fra hoved () tildeler yderligere hukommelse oven på den forrige stak. Dette gemmer:
    • Det det her objektreference for det kaldende objekt i stakhukommelsen
    • Den primitive værdi id i stakhukommelsen
    • Referencevariablen for Snor argument navn som peger på den aktuelle streng fra strengpool i hukommelseshukommelse
  3. Det vigtigste Metoden kalder yderligere buildPerson () statisk metode, for hvilken yderligere allokering finder sted i stakhukommelsen oven på den forrige. Dette lagrer igen variabler på den måde, der er beskrevet ovenfor.
  4. Dog for det nyoprettede objekt person af typen Person, vil alle instansvariabler blive gemt i heap-hukommelse.

Denne fordeling forklares i dette diagram:

5. Resume

Før vi afslutter denne artikel, lad os hurtigt opsummere forskellene mellem Stack Memory og Heap Space:

ParameterStak hukommelseHeap Space
AnsøgningStak bruges i dele, en ad gangen under udførelse af en trådHele applikationen bruger Heap space under runtime
StørrelseStack har størrelsesbegrænsninger afhængigt af operativsystem og er normalt mindre end HeapDer er ingen størrelsesbegrænsning på Heap
OpbevaringGemmer kun primitive variabler og referencer til objekter, der oprettes i Heap SpaceHer gemmes alle de nyoprettede objekter
BestilleDer er adgang til det ved hjælp af Last-in First-out (LIFO) hukommelsestildelingssystemDenne hukommelse tilgås via komplekse hukommelsesstyringsteknikker, der inkluderer Young Generation, Old eller Tenured Generation og Permanent Generation.
LivStack-hukommelse findes kun, så længe den aktuelle metode kørerDer findes bunkerum, så længe applikationen kører
EffektivitetForholdsmæssigt meget hurtigere at tildele sammenlignet med dyngLangsommere at tildele sammenlignet med stack
Tildeling / DeallocationDenne hukommelse tildeles og deallokeres automatisk, når en metode kaldes henholdsvis returneresBunkerum tildeles, når nye objekter oprettes og deallokeres af Gargabe Collector, når de ikke længere refereres til

6. Konklusion

Stak og bunke er to måder, hvorpå Java allokerer hukommelse. I denne artikel forstod vi, hvordan de fungerer, og hvornår de skal bruges til at udvikle bedre Java-programmer.

For at lære mere om Memory Management i Java, se denne artikel her. Vi diskuterede også JVM Garbage Collector, som diskuteres kort i denne artikel.