Spørgsmål om hukommelsesstyring i Java Interview (+ svar)

Denne artikel er en del af en serie: • Interviewsspørgsmål om Java Collections

• Spørgsmål om Java Type System Interview

• Java-spørgsmål om samtidige samtaler (+ svar)

• Interviewspørgsmål om Java-klassestruktur og initialisering

• Java 8 interviewspørgsmål (+ svar)

• Hukommelsesstyring i Java Interview-spørgsmål (+ svar) (nuværende artikel) • Java Generics-interviewspørgsmål (+ svar)

• Interviewspørgsmål til Java Flow Control (+ svar)

• Spørgsmål om Java-undtagelser (+ svar)

• Spørgsmål om Java-annotationer (+ svar)

• Top forårssamarbejdsspørgsmål

1. Introduktion

I denne artikel undersøger vi nogle hukommelsesadministrationsspørgsmål, der ofte dukker op under Java-udviklerinterviews. Hukommelsesstyring er et område, som ikke så mange udviklere kender.

Faktisk behøver udviklere generelt ikke at håndtere dette koncept direkte - da JVM tager sig af de detaljerede detaljer. Medmindre noget går alvorligt galt, har selv erfarne udviklere muligvis ikke nøjagtige oplysninger om hukommelsesadministration lige ved hånden.

På den anden side er disse begreber faktisk ret udbredte i interviews - så lad os hoppe lige ind.

2. Spørgsmål

Q1. Hvad betyder udsagnet "Hukommelse styres i Java"?

Hukommelse er nøgleressourcen, som en applikation kræver for at køre effektivt, og som enhver ressource er den knap. Som sådan kræver dets allokering og deallocation til og fra applikationer eller forskellige dele af en applikation en stor omhu og overvejelse.

I Java behøver en udvikler dog ikke eksplicit at allokere og deallokere hukommelse - JVM og mere specifikt Garbage Collector - har pligt til at håndtere hukommelsestildeling, så udvikleren ikke behøver det.

Dette er i modsætning til hvad der sker på sprog som C, hvor en programmør har direkte adgang til hukommelse og bogstaveligt talt refererer til hukommelsesceller i sin kode, hvilket skaber meget plads til hukommelseslækage.

Q2. Hvad er affaldsindsamling, og hvad er fordelene ved det?

Affaldssamling er processen med at se på bunkehukommelse, identificere hvilke objekter der er i brug og hvilke der ikke er, og slette de ubrugte objekter.

Et objekt i brug eller et refereret objekt betyder, at en del af dit program stadig opretholder en markør til det objekt. Et ubrugt objekt eller en ikke-refereret genstand henvises ikke længere til nogen del af dit program. Så den hukommelse, der bruges af et objekt uden referencer, kan genvindes.

Den største fordel ved skraldindsamling er, at det fjerner byrden ved manuel allokering / deallocation fra os, så vi kan fokusere på at løse det aktuelle problem.

Q3. Er der nogen ulemper ved affaldsindsamling?

Ja. Når affaldssamleren kører, har det en indvirkning på applikationens ydeevne. Dette skyldes, at alle andre tråde i applikationen skal stoppes for at gøre det muligt for affaldssamlertråden effektivt at udføre sit arbejde.

Afhængigt af kravene i applikationen kan dette være et reelt problem, der er uacceptabelt af klienten. Dette problem kan dog reduceres kraftigt eller endda elimineres gennem dygtig optimering og skraldesamlerindstilling og ved hjælp af forskellige GC-algoritmer.

Q4. Hvad betyder ordet "Stop-The-World"?

Når tråden til affaldssamleren kører, stoppes andre tråde, hvilket betyder, at applikationen stoppes et øjeblik. Dette er analogt med husrengøring eller gasning, hvor beboere nægtes adgang, indtil processen er afsluttet.

Afhængigt af applikationens behov kan affaldsindsamling med "stop the world" medføre en uacceptabel frysning. Dette er grunden til, at det er vigtigt at foretage skrotopsamlingsindstilling og JVM-optimering, så den frysning, der opstår, i det mindste er acceptabel.

Q5. Hvad er stak og bunke? Hvad gemmes i hver af disse hukommelsesstrukturer, og hvordan hænger de sammen?

Stakken er en del af hukommelsen, der indeholder information om indlejrede metodeopkald ned til den aktuelle position i programmet. Den indeholder også alle lokale variabler og referencer til objekter på bunken defineret i aktuelt udførende metoder.

Denne struktur gør det muligt for runtime at vende tilbage fra metoden og kende adressen, hvorfra den blev kaldt, og også rydde alle lokale variabler, efter at metoden var afsluttet. Hver tråd har sin egen stak.

Bunken er en stor del af hukommelsen beregnet til tildeling af objekter. Når du opretter et objekt med ny nøgleord, bliver det tildelt på bunken. Henvisningen til dette objekt lever imidlertid på stakken.

Q6. Hvad er generation af affaldsindsamling, og hvad gør det til en populær fremgangsmåde til indsamling af affald?

Generationsaffaldsindsamling kan defineres løst som strategien, der bruges af affaldssamleren, hvor bunken er opdelt i et antal sektioner kaldet generationer, som hver især vil rumme genstande i henhold til deres "alder" på bunken.

Når affaldssamleren kører, kaldes det første trin i processen mærkning. Det er her affaldssamleren identificerer, hvilke hukommelsesstykker der er i brug, og hvilke der ikke er. Dette kan være en meget tidskrævende proces, hvis alle objekter i et system skal scannes.

Når flere og flere objekter tildeles, vokser listen over objekter og vokser, hvilket fører til længere og længere tid til indsamling af affald. Imidlertid har empirisk analyse af applikationer vist, at de fleste objekter er kortvarige.

Med generation af skraldindsamling grupperes objekter efter deres "alder" med hensyn til hvor mange skraldopsamlingscyklusser de har overlevet. På denne måde spredte hovedparten af ​​arbejdet sig over forskellige mindre og større indsamlingscyklusser.

I dag er næsten alle affaldssamlere generation. Denne strategi er så populær, fordi den over tid har vist sig at være den optimale løsning.

Q7. Beskriv detaljeret, hvordan Generation Garbage Collection fungerer

For at forstå korrekt, hvordan generation af affaldsindsamling fungerer, er det vigtigt først husk hvordan Java bunke er struktureret for at lette generationens affaldsindsamling.

Bunken er opdelt i mindre rum eller generationer. Disse rum er Young Generation, Old eller Tenured Generation og Permanent Generation.

Det ung generation er vært for de fleste af de nyoprettede objekter. En empirisk undersøgelse af de fleste applikationer viser, at størstedelen af ​​objekter hurtigt er kortvarige og derfor snart bliver berettiget til indsamling. Derfor begynder nye objekter deres rejse her og bliver først "forfremmet" til den gamle generation, når de har nået en bestemt "alder".

Begrebet "alder" i generationens affaldsindsamling henviser til antallet af indsamlingscyklusser, som objektet har overlevet.

Det unge generations rum er yderligere opdelt i tre rum: et Eden-rum og to overlevende rum såsom Survivor 1 (s1) og Survivor 2 (s2).

Det gamle generation er vært for objekter, derhar levet i hukommelsen længere end en bestemt "alder". Objekterne, der overlevede affaldssamling fra den unge generation, fremmes til dette rum. Det er generelt større end den unge generation. Da det er større i størrelse, er affaldssamlingen dyrere og forekommer sjældnere end i den unge generation.

Det permanent generationeller mere almindeligt kaldet, PermGen, indeholder metadata, der kræves af JVM til at beskrive de klasser og metoder, der anvendes i applikationen. Den indeholder også strengpoolen til lagring af internede strenge. Det er befolket af JVM ved runtime baseret på klasser, der bruges af applikationen. Derudover kan klasser og metoder til platformbiblioteker gemmes her.

Først, eventuelle nye objekter er allokeret til Eden-rummet. Begge overlevende rum starter tomme. Når Eden-rummet er fyldt, udløses en mindre affaldsindsamling. Henviste objekter flyttes til det første overlevende rum. Ikke-henviste objekter slettes.

Under den næste mindre GC sker det samme med Eden-rummet. Ikke-henviste objekter slettes, og henviste objekter flyttes til et overlevende rum. I dette tilfælde flyttes de imidlertid til det andet overlevende rum (S2).

Derudover har objekter fra den sidste mindre GC i det første overlevende rum (S1) deres alder forøget og flyttes til S2. Når alle overlevende objekter er flyttet til S2, ryddes både S1 og Eden-pladsen. På dette tidspunkt indeholder S2 objekter med forskellige aldre.

Ved den næste mindre GC gentages den samme proces. Men denne gang skifter de overlevende rum. Henviste objekter flyttes til S1 fra både Eden og S2. Overlevende genstande ældes. Eden og S2 er ryddet.

Efter hver mindre affaldsindsamlingscyklus kontrolleres alder på hvert objekt. De, der har nået en vis vilkårlig alder, for eksempel 8, forfremmes fra den unge generation til den gamle eller fastansatte generation. I alle efterfølgende mindre GC-cyklusser promoveres objekter til det gamle generationsrum.

Dette udnytter stort set processen med affaldsindsamling i den unge generation. Til sidst vil der blive udført en større affaldssamling på den gamle generation, som renser og komprimerer dette rum. For hver større GC er der flere mindre GC'er.

Q8. Hvornår bliver et objekt berettiget til indsamling af affald? Beskriv hvordan Gc samler et kvalificeret objekt?

Et objekt bliver kvalificeret til affaldssamling eller GC, hvis det ikke kan nås fra nogen live tråde eller ved hjælp af statiske referencer.

Det mest ligefremme tilfælde af, at et objekt bliver kvalificeret til affaldsindsamling, er, hvis alle dets referencer er nul. Cykliske afhængigheder uden nogen ekstern live-reference er også berettigede til GC. Så hvis objekt A henviser til objekt B og objekt B henviser til objekt A, og de ikke har nogen anden levende reference, er begge objekter A og B kvalificerede til affaldssamling.

Et andet åbenlyst tilfælde er, når et overordnet objekt er indstillet til null. Når et køkkenobjekt internt refererer til et køleskabsobjekt og et vaskeobjekt, og køkkenobjektet er indstillet til null, vil både køleskab og vask blive kvalificeret til affaldsindsamling sammen med deres forælder, køkkenet.

Q9. Hvordan udløser du affaldssamling fra Java-kode?

Du som Java-programmør kan ikke tvinge skraldindsamling i Java; det udløses kun, hvis JVM mener, at det har brug for en affaldssamling baseret på Java-bunkestørrelse.

Før en genstand fjernes fra hukommelsen, påkalder tråden affald finalize () -metoden for det pågældende objekt og giver mulighed for at foretage enhver form for oprydning, der kræves. Du kan også påberåbe sig denne metode til en objektkode, men der er ingen garanti for, at affaldsopsamling sker, når du kalder denne metode.

Derudover er der metoder som System.gc () og Runtime.gc (), der bruges til at sende anmodning om affaldsindsamling til JVM, men det er ikke garanteret, at affaldsindsamling sker.

Q10. Hvad sker der, når der ikke er tilstrækkelig masser af plads til opbevaring af nye genstande?

Hvis der ikke er plads til hukommelse til oprettelse af et nyt objekt i Heap, kaster Java Virtual Machine OutOfMemoryError eller mere specifiktjava.lang.OutOfMemoryError bunkeplads.

Q11. Er det muligt at "genoplive" et objekt, der blev kvalificeret til affaldsindsamling?

Når et objekt bliver kvalificeret til affaldsindsamling, skal GC køre færdiggør metode på det. Det færdiggør metoden er garanteret at køre kun en gang, så GC markerer objektet som afsluttet og giver det en pause indtil næste cyklus.

I færdiggør metode kan du teknisk “genoplive” et objekt, for eksempel ved at tildele det til en statisk Mark. Objektet ville blive levende igen og ikke være berettiget til indsamling af affald, så GC ville ikke indsamle det i løbet af den næste cyklus.

Objektet vil dog blive markeret som færdiggjort, så når det bliver kvalificeret igen, vil den færdige metode ikke kaldes. I det væsentlige kan du kun vende dette “opstandelsestrik” en gang i objektets levetid. Pas på, at dette grimme hack kun skal bruges, hvis du virkelig ved, hvad du laver - men at forstå dette trick giver noget indblik i, hvordan GC fungerer.

Q12. Beskriv stærke, svage, bløde og fantomreferencer og deres rolle i affaldssamlingen.

Meget som hukommelse administreres i Java, kan en ingeniør muligvis udføre så meget optimering som muligt for at minimere latenstid og maksimere kapacitet i kritiske applikationer. Meget som det er umuligt at udtrykkeligt kontrollere, hvornår skraldindsamling udløses i JVM, det er muligt at påvirke, hvordan det opstår med hensyn til de objekter, vi har skabt.

Java giver os referenceobjekter til at kontrollere forholdet mellem de objekter, vi opretter, og affaldssamleren.

Som standard henvises der til ethvert objekt, vi opretter i et Java-program, af en variabel:

StringBuilder sb = ny StringBuilder ();

I ovenstående uddrag er ny nøgleord opretter et nyt StringBuilder objekt og gemmer det på bunken. Variablen sb gemmer derefter en stærk reference til dette objekt. Hvad dette betyder for affaldssamleren er, at det særlige StringBuilder objekt er overhovedet ikke berettiget til indsamling på grund af en stærk henvisning til det af sb. Historien ændres kun, når vi annullerer sb sådan her:

sb = null;

Efter at have ringet til ovenstående linje er objektet så berettiget til indsamling.

Vi kan ændre dette forhold mellem objektet og affaldssamleren ved eksplicit at indpakke det i et andet referenceobjekt, der er placeret indeni java.lang.ref pakke.

EN blød reference kan oprettes til ovenstående objekt på denne måde:

StringBuilder sb = ny StringBuilder (); SoftReference sbRef = ny SoftReference (sb); sb = null;

I ovenstående uddrag har vi oprettet to referencer til StringBuilder objekt. Den første linje opretter en stærk referencesb og den anden linje opretter en blød referencesbRef. Den tredje linje skal gøre objektet berettiget til indsamling, men affaldssamleren udsætter indsamlingen på grund af sbRef.

Historien vil kun ændre sig, når hukommelsen bliver stram, og JVM er på randen af ​​at kaste en Ikke mere hukommelse fejl. Med andre ord samles objekter med kun bløde referencer som en sidste udvej for at gendanne hukommelse.

EN svag reference kan oprettes på en lignende måde ved hjælp af Svag henvisning klasse. Hvornår sb er indstillet til null og StringBuilder objekt har kun en svag reference, JVM's affaldssamler har absolut intet kompromis og straks indsamler objektet i den næste cyklus.

EN fantomreference svarer til en svag reference, og et objekt med kun fantomreferencer vil blive samlet uden at vente. Imidlertid er fantomreferencer indkapslet, så snart deres genstande er samlet. Vi kan afstemme referencekøen for at vide nøjagtigt, hvornår objektet blev samlet.

Q13. Antag, at vi har en cirkulær reference (to objekter, der refererer til hinanden). Kunne et sådant par genstande være berettiget til indsamling af affald, og hvorfor?

Ja, et par genstande med en cirkulær reference kan blive berettiget til affaldsindsamling. Dette skyldes, hvordan Java's affaldssamler håndterer cirkulære referencer. Det betragter objekter som levende, ikke når de har nogen henvisning til dem, men når de kan nås ved at navigere i objektgrafen med udgangspunkt i en eller anden affaldssamlingsrod (en lokal variabel i en live tråd eller et statisk felt). Hvis et par objekter med en cirkulær reference ikke kan nås fra nogen rod, betragtes det som berettiget til affaldsindsamling.

Q14. Hvordan er strenge repræsenteret i hukommelsen?

EN Snor forekomst i Java er et objekt med to felter: a char [] værdi felt og et int hash Mark. Det værdi felt er en række af tegn, der repræsenterer selve strengen og hash feltet indeholder hashCode af en streng, der initialiseres med nul, beregnet i løbet af den første hashCode () opkald og cache lige siden. Som en nysgerrig kant sag, hvis en hashCode af en streng har en nulværdi, skal den genberegnes hver gang hashCode () Hedder.

Vigtig ting er, at en Snor eksempel er uforanderlig: du kan ikke hente eller ændre det underliggende char [] array. Et andet træk ved strenge er, at de statiske konstante strenge indlæses og caches i en strengpool. Hvis du har flere identiske Snor objekter i din kildekode, de er alle repræsenteret af en enkelt forekomst ved kørsel.

Q15. Hvad er en strengbygger, og hvad er brugen af ​​dens tilfælde? Hvad er forskellen mellem at tilføje en streng til en strengbygger og sammenkæde to strenge med en + operatør? Hvordan adskiller sig strengbygger fra Stringbuffer?

StringBuilder tillader manipulation af tegnsekvenser ved at tilføje, slette og indsætte tegn og strenge. Dette er en ændret datastruktur i modsætning til Snor klasse, som er uforanderlig.

Ved sammenkædning af to Snor tilfælde oprettes et nyt objekt, og strenge kopieres. Dette kan medføre en enorm affaldssamler, hvis vi har brug for at oprette eller ændre en streng i en løkke. StringBuilder tillader håndtering af strengmanipulationer meget mere effektivt.

StringBuffer er forskellig fra StringBuilder ved at det er trådsikkert. Hvis du har brug for at manipulere en streng i en enkelt tråd, skal du bruge StringBuilder i stedet.

3. Konklusion

I denne artikel har vi dækket nogle af de mest almindelige spørgsmål, der ofte vises i Java-ingeniørinterviews. Spørgsmål om hukommelsesadministration stilles for det meste til Senior Java Developer-kandidater, da intervieweren forventer, at du har bygget ikke-trivielle applikationer, der ofte er plaget af hukommelsesproblemer.

Dette bør ikke behandles som en udtømmende liste med spørgsmål, men snarere en startpude til yderligere forskning. Vi i Baeldung ønsker dig succes i alle kommende interviews.

Næste » Java Generics Interview Spørgsmål (+ svar) « Tidligere Java 8 interviewspørgsmål (+ svar)