Het begrijpen van de JVM-geheugenmodel, Java-geheugenbeheer is erg belangrijk als u het functioneren van Java Garbage Collection wilt begrijpen. Vandaag zullen we kijken naar geheugenbeheer in Java, de verschillende delen van het JVM-geheugen en hoe u het kunt controleren en garbage collection-tuning kunt uitvoeren.
Java (JVM) Geheugenmodel
Zoals u kunt zien in de bovenstaande afbeelding, is het JVM-geheugen verdeeld in aparte delen. Op een hoog niveau is het JVM-heapgeheugen fysiek verdeeld in twee delen – Young Generation en Old Generation.
Geheugenbeheer in Java – Young Generation
De young generation is de plaats waar alle nieuwe objecten worden gemaakt. Wanneer de young generation vol is, wordt garbage collection uitgevoerd. Deze garbage collection wordt Minor GC genoemd. Young Generation is verdeeld in drie delen – Eden-geheugen en twee Survivor-geheugen ruimtes. Belangrijke punten over Young Generation Spaces:
- Het merendeel van de nieuw gecreëerde objecten bevindt zich in de Eden-geheugenruimte.
- Wanneer de Eden-ruimte gevuld is met objecten, wordt er een Minor GC uitgevoerd en worden alle overlevende objecten verplaatst naar een van de overlevendenruimtes.
- Minor GC controleert ook de overlevende objecten en verplaatst ze naar de andere overlevendenruimte. Dus op een gegeven moment is een van de overlevendenruimtes altijd leeg.
- Objecten die na vele cycli van GC hebben overleefd, worden verplaatst naar de geheugenruimte van de Oude generatie. Meestal wordt dit gedaan door een drempel in te stellen voor de leeftijd van de objecten in de jonge generatie voordat ze in aanmerking komen om te worden gepromoveerd naar de Oude generatie.
Geheugenbeheer in Java – Oude Generatie
De geheugenruimte van de Oude Generatie bevat objecten die langdurig zijn en hebben overleefd na vele rondes van Minor GC. Meestal wordt garbage collection uitgevoerd in de geheugenruimte van de Oude Generatie wanneer deze vol is. Garbage Collection in de Oude Generatie wordt een Major GC genoemd en duurt meestal langer.
Stop het Wereld Evenement
Alle Garbage Collections zijn “Stop de Wereld” gebeurtenissen omdat alle toepassingsthreads worden gestopt totdat de operatie is voltooid. Aangezien de Young-generatie kortlevende objecten bevat, is Minor GC erg snel en wordt de toepassing hierdoor niet beïnvloed. Echter, Major GC duurt lang omdat het alle levende objecten controleert. Major GC moet worden geminimaliseerd omdat het uw toepassing onresponsief maakt gedurende de duur van de garbage collection. Dus als u een responsieve toepassing heeft en er veel Major Garbage Collections plaatsvinden, zult u time-outfouten opmerken. De duur van de garbage collector hangt af van de strategie die wordt gebruikt voor garbage collection. Daarom is het noodzakelijk om de garbage collector te monitoren en af te stemmen om time-outs te vermijden in zeer responsieve toepassingen.
Java Memory Model – Permanente Generatie
De Permanente Generatie of “Perm Gen” bevat de toepassingsmetadata die door de JVM wordt vereist om de klassen en methoden die in de toepassing worden gebruikt, te beschrijven. Let op dat Perm Gen geen onderdeel is van het Java Heap-geheugen. Perm Gen wordt door de JVM op runtime ingevuld op basis van de door de toepassing gebruikte klassen. Perm Gen bevat ook klassen en methoden van de Java SE-bibliotheek. Perm Gen-objecten worden verzameld tijdens een volledige garbage collection.
Java-geheugenmodel – Methodegebied
Het methodegebied maakt deel uit van de ruimte in de Perm Gen en wordt gebruikt om de klassenstructuur (runtime-constanten en statische variabelen) en de code voor methoden en constructeurs op te slaan.
Java-geheugenmodel – Geheugenpool
Geheugenpools worden door JVM-geheugenbeheerders gemaakt om een pool van onveranderlijke objecten te creëren als de implementatie dit ondersteunt. De String Pool is een goed voorbeeld van dit soort geheugenpool. De geheugenpool kan behoren tot de Heap of Perm Gen, afhankelijk van de implementatie van de JVM-geheugenbeheerder.
Java-geheugenmodel – Runtime-constante pool
De runtime-constante pool is een per-klasse runtime-vertegenwoordiging van de constante pool in een klasse. Het bevat runtime-constanten van klassen en statische methoden. De runtime-constante pool maakt deel uit van het methodegebied.
Java Geheugenmodel – Java Stackgeheugen
Het Java Stack-geheugen wordt gebruikt voor de uitvoering van een thread. Ze bevatten methode-specifieke waarden die van korte duur zijn en verwijzingen naar andere objecten in de heap die vanuit de methode worden doorverwezen. Je moet Het verschil tussen Stack- en Heap-geheugen lezen.
Geheugenbeheer in Java – Java Heap-geheugenschakelaars
Java biedt veel geheugenschakelaars die we kunnen gebruiken om de geheugengroottes en hun verhoudingen in te stellen. Enkele van de veelgebruikte geheugenschakelaars zijn:
VM Switch | VM Switch Description |
---|---|
-Xms | For setting the initial heap size when JVM starts |
-Xmx | For setting the maximum heap size. |
-Xmn | For setting the size of the Young Generation, rest of the space goes for Old Generation. |
-XX:PermGen | For setting the initial size of the Permanent Generation memory |
-XX:MaxPermGen | For setting the maximum size of Perm Gen |
-XX:SurvivorRatio | For providing ratio of Eden space and Survivor Space, for example if Young Generation size is 10m and VM switch is -XX:SurvivorRatio=2 then 5m will be reserved for Eden Space and 2.5m each for both the Survivor spaces. The default value is 8. |
-XX:NewRatio | For providing ratio of old/new generation sizes. The default value is 2. |
Meestal zijn bovenstaande opties voldoende, maar als je ook andere opties wilt bekijken, controleer dan De officiële pagina van JVM-opties.
Geheugenbeheer in Java – Java Garbage Collection
Java Garbage Collection is het proces om de ongebruikte objecten in het geheugen te identificeren en te verwijderen en ruimte vrij te maken om te worden toegewezen aan objecten die in de toekomst worden verwerkt. Een van de beste functies van de Java-programmeertaal is de automatische garbage collection, in tegenstelling tot andere programmeertalen zoals C waar geheugenallocatie en deallocatie een handmatig proces is. Garbage Collector is het programma dat op de achtergrond draait en alle objecten in het geheugen bekijkt en objecten identificeert die niet worden verwezen door een deel van het programma. Al deze niet-verwezen objecten worden verwijderd en de ruimte wordt herwonnen voor toewijzing aan andere objecten. Een van de basismanieren van garbage collection omvat drie stappen:
- Markeren: Dit is de eerste stap waarin de garbage collector identificeert welke objecten in gebruik zijn en welke niet.
- Normale Verwijdering: De Garbage Collector verwijdert de ongebruikte objecten en herwint de vrije ruimte om te worden toegewezen aan andere objecten.
- Verwijdering met Comprimeren: Voor betere prestaties kunnen na het verwijderen van ongebruikte objecten alle overgebleven objecten worden verplaatst om bij elkaar te staan. Dit zal de prestaties van de toewijzing van geheugen aan nieuwere objecten verbeteren.
Er zijn twee problemen met een eenvoudige markeer-en-verwijderaanpak.
- Het eerste probleem is dat het niet efficiënt is omdat de meeste nieuw gemaakte objecten ongebruikt zullen blijven
- Ten tweede zijn objecten die gedurende meerdere garbage collection-cycli in gebruik zijn, waarschijnlijk ook in gebruik voor toekomstige cycli.
De bovengenoemde tekortkomingen van de eenvoudige aanpak zijn de reden dat Java Garbage Collection Generatiegericht is en we Jonge Generatie en Oude Generatie ruimtes hebben in het heapgeheugen. Ik heb hierboven al uitgelegd hoe objecten worden gescand en verplaatst van de ene generatieruimte naar de andere op basis van de Minor GC en Major GC.
Geheugenbeheer in Java – Typen Java Garbage Collection
Er zijn vijf soorten garbage collection die we kunnen gebruiken in onze applicaties. We hoeven alleen de JVM-switch te gebruiken om de garbage collection-strategie voor de applicatie in te schakelen. Laten we ze een voor een bekijken.
- Seriele GC (-XX:+UseSerialGC): Seriële GC gebruikt de eenvoudige mark-sweep-compact benadering voor het verzamelen van garbage in jonge en oude generaties, d.w.z. Minor en Major GC. Seriële GC is nuttig op clientmachines zoals onze eenvoudige stand-alone applicaties en machines met kleinere CPU’s. Het is goed voor kleine applicaties met een lage geheugenfootprint.
- Parallel GC (-XX:+UseParallelGC): Parallel GC is hetzelfde als Serial GC, behalve dat het N threads creëert voor garbage collection in de jonge generatie, waarbij N het aantal CPU-cores in het systeem is. We kunnen het aantal threads beheren met behulp van de
-XX:ParallelGCThreads=n
JVM-optie. Parallel Garbage Collector wordt ook wel de throughput-collector genoemd omdat het meerdere CPU’s gebruikt om de prestaties van de GC te versnellen. Parallel GC gebruikt één thread voor garbage collection in de oude generatie. - Parallel Old GC (-XX:+UseParallelOldGC): Dit is hetzelfde als Parallel GC, behalve dat het meerdere threads gebruikt voor zowel garbage collection in de jonge generatie als in de oude generatie.
- Concurrent Mark Sweep (CMS) Collector (-XX:+UseConcMarkSweepGC): CMS Collector wordt ook wel de gelijktijdige low-pauze-collector genoemd. Het doet de garbage collection voor de oude generatie. CMS collector probeert de onderbrekingen als gevolg van garbage collection te minimaliseren door het grootste deel van het garbage collection-werk gelijktijdig met de applicatietaken uit te voeren. CMS collector gebruikt hetzelfde algoritme als dat van de parallelle collector voor de jonge generatie. Deze garbage collector is geschikt voor responsieve applicaties waar we ons geen langere pauzetijden kunnen veroorloven. We kunnen het aantal threads in CMS collector beperken met behulp van de
-XX:ParallelCMSThreads=n
JVM-optie. - G1 Garbage Collector (-XX:+UseG1GC): De Garbage First of G1 garbage collector is beschikbaar vanaf Java 7 en heeft als langetermijndoel om de CMS collector te vervangen. De G1-collector is een parallelle, gelijktijdige en incrementele compacte garbage collector met lage pauzes. De Garbage First Collector werkt niet zoals andere collectors en er is geen concept van Young en Old generation space. Het verdeelt de heap space in meerdere gelijkwaardige heap-regio’s. Wanneer een garbage collection wordt geactiveerd, verzamelt het eerst de regio met minder live data, vandaar “Garbage First”. U kunt meer details vinden op Garbage-First Collector Oracle Documentation.
Memory Management in Java – Java Garbage Collection Monitoring
We kunnen zowel de Java-opdrachtregel als UI-tools gebruiken om de garbage collection-activiteiten van een applicatie te monitoren. Voor mijn voorbeeld gebruik ik een van de demo-applicaties die worden geleverd bij Java SE-downloads. Als je dezelfde applicatie wilt gebruiken, ga dan naar de Java SE Downloads-pagina en download JDK 7 en JavaFX Demos en Samples. De voorbeeldapplicatie die ik gebruik is Java2Demo.jar en deze bevindt zich in de map jdk1.7.0_55/demo/jfc/Java2D
. Dit is echter een optionele stap en je kunt de GC-monitoringopdrachten uitvoeren voor elke Java-applicatie. Het commando dat ik gebruik om de demo-applicatie te starten is:
pankaj@Pankaj:~/Downloads/jdk1.7.0_55/demo/jfc/Java2D$ java -Xmx120m -Xms30m -Xmn10m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseSerialGC -jar Java2Demo.jar
jstat
We kunnen de jstat
-opdrachtregeltool gebruiken om het geheugen van de JVM en de garbage collection-activiteiten te monitoren. Het wordt meegeleverd met de standaard JDK, dus je hoeft niets anders te doen om het te krijgen. Om jstat
uit te voeren, moet je de proces-ID van de applicatie weten, die je gemakkelijk kunt krijgen met het ps -eaf | grep java
-commando.
pankaj@Pankaj:~$ ps -eaf | grep Java2Demo.jar
501 9582 11579 0 9:48PM ttys000 0:21.66 /usr/bin/java -Xmx120m -Xms30m -Xmn10m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseG1GC -jar Java2Demo.jar
501 14073 14045 0 9:48PM ttys002 0:00.00 grep Java2Demo.jar
Dus de proces-ID voor mijn Java-applicatie is 9582. Nu kunnen we het jstat-commando uitvoeren zoals hieronder weergegeven.
pankaj@Pankaj:~$ jstat -gc 9582 1000
S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT
1024.0 1024.0 0.0 0.0 8192.0 7933.3 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654
1024.0 1024.0 0.0 0.0 8192.0 8026.5 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654
1024.0 1024.0 0.0 0.0 8192.0 8030.0 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654
1024.0 1024.0 0.0 0.0 8192.0 8122.2 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654
1024.0 1024.0 0.0 0.0 8192.0 8171.2 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654
1024.0 1024.0 48.7 0.0 8192.0 106.7 42108.0 23401.3 20480.0 19990.9 158 0.275 40 1.381 1.656
1024.0 1024.0 48.7 0.0 8192.0 145.8 42108.0 23401.3 20480.0 19990.9 158 0.275 40 1.381 1.656
Het laatste argument voor jstat is het tijdsinterval tussen elke output, dus het zal geheugen- en garbage collection-gegevens elke 1 seconde afdrukken. Laten we elk van de kolommen stap voor stap doornemen.
- S0C en S1C: Deze kolom toont de huidige grootte van de Survivor0- en Survivor1-gebieden in KB.
- S0U en S1U: Deze kolom toont het huidige gebruik van de Survivor0- en Survivor1-gebieden in KB. Let op dat een van de survivor-gebieden altijd leeg is.
- EC en EU: Deze kolommen tonen de huidige grootte en gebruik van Eden-ruimte in KB. Merk op dat de EU-grootte toeneemt en zodra deze de EC overschrijdt, wordt Minor GC aangeroepen en wordt de EU-grootte verlaagd.
- OC en OU: Deze kolommen tonen de huidige grootte en huidig gebruik van de oude generatie in KB.
- PC en PU: Deze kolommen tonen de huidige grootte en huidig gebruik van Perm Gen in KB.
- YGC en YGCT: De YGC-kolom geeft het aantal GC-gebeurtenissen weer die hebben plaatsgevonden in de jonge generatie. De YGCT-kolom geeft de opgetelde tijd weer voor GC-operaties voor de jonge generatie. Let op dat beide toenemen in dezelfde rij waar de EU-waarde daalt als gevolg van een Minor GC.
- FGC en FGCT: De FGC-kolom geeft het aantal Full GC-gebeurtenissen weer die hebben plaatsgevonden. De FGCT-kolom geeft de opgetelde tijd weer voor Full GC-operaties. Merk op dat de tijd voor Full GC te hoog is in vergelijking met de GC-tijden van de jonge generatie.
- GCT: Deze kolom geeft de totale opgetelde tijd weer voor GC-operaties. Merk op dat het de som is van de waarden in de YGCT- en FGCT-kolommen.
Het voordeel van jstat is dat het ook kan worden uitgevoerd op externe servers waar geen GUI beschikbaar is. Let op dat de som van S0C, S1C en EC 10 m is zoals gespecificeerd via de -Xmn10m
JVM-optie.
Java VisualVM met Visual GC
Als je geheugen- en GC-operaties wilt bekijken in een GUI, dan kun je de tool jvisualvm
gebruiken. Java VisualVM maakt ook deel uit van JDK, dus je hoeft het niet apart te downloaden. Voer gewoon het jvisualvm
-commando uit in de terminal om de Java VisualVM-toepassing te starten. Nadat deze is gestart, moet je de Visual GC-plugin installeren vanuit het menu Tools -> Plugins, zoals getoond in onderstaande afbeelding. Na de installatie van Visual GC, open je de toepassing aan de linkerkant en ga je naar de Visual GC-sectie. Je krijgt een afbeelding van JVM-geheugen en details over garbage collection, zoals getoond in onderstaande afbeelding.
Java Garbage Collection Tuning
Java Garbage Collection Tuning moet de laatste optie zijn die je gebruikt om de doorvoer van je toepassing te verhogen en alleen wanneer je een prestatiedaling ziet vanwege langere GC-tijden die applicatie time-outs veroorzaken. Als je java.lang.OutOfMemoryError: PermGen space
fouten ziet in logs, probeer dan de Perm Gen-geheugenruimte te controleren en te vergroten met behulp van -XX:PermGen en -XX:MaxPermGen JVM-opties. Je kunt ook proberen -XX:+CMSClassUnloadingEnabled
te gebruiken en controleren hoe het presteert met de CMS Garbage-collector. Als je veel Full GC-operaties ziet, moet je proberen de geheugenruimte van de Oude generatie te vergroten. Over het algemeen vergt het afstemmen van de garbage collection veel inspanning en tijd en er is geen harde en snelle regel voor. Je zou verschillende opties moeten proberen en ze vergelijken om de beste geschikte voor jouw toepassing te vinden. Dat is alles voor het Java Memory Model, Memory Management in Java en Garbage Collection. Ik hoop dat het je helpt bij het begrijpen van het JVM-geheugen en het garbage collection-proces.
Source:
https://www.digitalocean.com/community/tutorials/java-jvm-memory-model-memory-management-in-java