Share via


Java-geheugenbeheer

Notitie

Azure Spring Apps is de nieuwe naam voor de Azure Spring Cloud-service. Hoewel de service een nieuwe naam heeft, ziet u de oude naam op sommige plaatsen terwijl we werken aan het bijwerken van assets, zoals schermopnamen, video's en diagrammen.

Dit artikel is van toepassing op: ✔️ Basic/Standard ✔️ Enterprise

In dit artikel worden verschillende concepten beschreven met betrekking tot Java-geheugenbeheer, zodat u inzicht krijgt in het gedrag van Java-toepassingen die worden gehost in Azure Spring Apps.

Java-geheugenmodel

Het geheugen van een Java-toepassing heeft verschillende onderdelen en er zijn verschillende manieren om de onderdelen te verdelen. In dit artikel wordt Java-geheugen besproken, zoals onderverdeeld in heap-geheugen, niet-heapgeheugen en direct geheugen.

Heap-geheugen

Heap-geheugen slaat alle klasse-exemplaren en matrices op. Elke virtuele Java-machine (JVM) heeft slechts één heapgebied, dat wordt gedeeld tussen threads.

Spring Boot Actuator kan de waarde van heap geheugen observeren. Spring Boot Actuator neemt de heap-waarde als onderdeel van jvm.memory.used/committed/max. Zie de sectie jvm.memory.used/commit/max in Tools voor het oplossen van geheugenproblemen voor meer informatie.

Heap geheugen is verdeeld in jonge generatie en oude generatie. Deze termen worden beschreven in de volgende lijst, samen met gerelateerde termen.

  • Jonge generatie: alle nieuwe objecten worden toegewezen en oud in jonge generatie.

    • Eden-ruimte: nieuwe objecten worden toegewezen in Eden-ruimte.
    • Overlevende ruimte: objecten worden verplaatst van Eden naar overlevende ruimte na het overleven van één garbagecollectioncyclus. Overlevende ruimte kan worden verdeeld in twee delen: s1 en s2.
  • Oude generatie: ook wel gewelfde ruimte genoemd. Objecten die gedurende lange tijd in de overlevende ruimten zijn gebleven, worden verplaatst naar de oude generatie.

Vóór Java 8 maakte een andere sectie met de naam permanente generatie ook deel uit van de heap. Vanaf Java 8 werd permanente generatie vervangen door metaspace in niet-heap-geheugen.

Geheugen zonder heap

Niet-heapgeheugen is onderverdeeld in de volgende onderdelen:

  • Het deel van niet-heapgeheugen dat de permanente generatie (of permGen) vervangt vanaf Java 8. Spring Boot Actuator observeert deze sectie en neemt het mee als onderdeel van jvm.memory.used/committed/max. Met andere woorden, jvm.memory.used/committed/max is de som van heap geheugen en het voormalige permGen deel van niet-heap geheugen. De voormalige permanente generatie bestaat uit de volgende onderdelen:

    • Metaspace, waarin de klassedefinities worden opgeslagen die door klasseladers worden geladen.
    • Gecomprimeerde klasseruimte, voor gecomprimeerde klassepointers.
    • Codecache, waarin systeemeigen code wordt opgeslagen die is gecompileerd door JIT.
  • Ander geheugen, zoals de threadstack, die niet wordt waargenomen door Spring Boot Actuator.

Direct geheugen

Direct geheugen is systeemeigen geheugen toegewezen door java.nio.DirectByteBuffer, dat wordt gebruikt in bibliotheken van derden, zoals nio en gzip.

Spring Boot Actuator ziet niet de waarde van direct geheugen.

In het volgende diagram ziet u een overzicht van het Java-geheugenmodel dat in de vorige sectie is beschreven.

Diagram met het Java-geheugenmodel.

Java garbagecollection

Er zijn drie termen met betrekking tot Java Garbage Collection (GC): "Minor GC", "Major GC" en "Full GC". Deze termen zijn niet duidelijk gedefinieerd in de JVM-specificatie. Hier beschouwen we 'Major GC' en 'Full GC' als equivalent.

Kleine GC voert uit wanneer de ruimte in Eden vol is. Het verwijdert alle dode objecten in jonge generatie en verplaatst levende objecten van Eden ruimte naar s1 van overlevende ruimte, of van s1 naar s2.

Volledige GC of grote GC doet garbagecollection in de hele heap. Volledige GC kan ook delen zoals metaspace en direct geheugen verzamelen, die alleen kunnen worden opgeschoond door volledige GC.

De maximale heapgrootte is van invloed op de frequentie van secundaire GC en volledige GC. De maximale metaspace en maximale directe geheugengrootte beïnvloeden volledige GC.

Wanneer u de maximale heap-grootte instelt op een lagere waarde, treden garbagecollections vaker op, waardoor de app een beetje wordt vertraagd, maar het geheugengebruik beter wordt beperkt. Wanneer u de maximale heap-grootte instelt op een hogere waarde, treden garbagecollections minder vaak op, waardoor er mogelijk meer risico op onvoldoende geheugen (OOM) ontstaat. Zie de sectie Over problemen met onvoldoende geheugen van de app die worden veroorzaakt door problemen met onvoldoende geheugen voor meer informatie.

Metaspace en direct geheugen kunnen alleen worden verzameld door volledige GC. Wanneer metaspace of direct geheugen vol is, vindt volledige GC plaats.

Java-geheugenconfiguraties

In de volgende secties worden belangrijke aspecten van de java-geheugenconfiguratie beschreven.

Java-containerisatie

Toepassingen in Azure Spring Apps worden uitgevoerd in containeromgevingen. Zie Containerize uw Java-toepassingen voor meer informatie.

Belangrijke JVM-opties

U kunt de maximale grootte van elk deel van het geheugen configureren met behulp van JVM-opties. U kunt JVM-opties instellen met behulp van Azure CLI-opdrachten of via Azure Portal. Zie voor meer informatie de sectie Configuraties wijzigen om problemen op te lossen van Hulpprogramma's om geheugenproblemen op te lossen.

In de volgende lijst worden de JVM-opties beschreven:

  • Configuratie van heap-grootte

    • -Xms stelt de oorspronkelijke heapgrootte in op absolute waarde.
    • -Xmx stelt de maximale heapgrootte in op absolute waarde.
    • -XX:InitialRAMPercentage stelt de oorspronkelijke heapgrootte in op basis van het percentage heap-grootte/app-geheugengrootte.
    • -XX:MaxRAMPercentage stelt de maximale heapgrootte in op het percentage heap-grootte/app-geheugengrootte.
  • Configuratie van directe geheugengrootte

    • -XX:MaxDirectMemorySize stelt de maximale grootte van het directe geheugen in op absolute waarde. Zie MaxDirectMemorySize in de Oracle-documentatie voor meer informatie.
  • Configuratie van metaruimtegrootte

    • -XX:MaxMetaspaceSize stelt de maximale grootte van de metaruimte in op absolute waarde.

Standaard maximale geheugengrootte

In de volgende secties wordt beschreven hoe standaard maximale geheugengrootten worden ingesteld.

Standaard maximale heapgrootte

Azure Spring Apps stelt de standaard maximale heap-geheugengrootte in op ongeveer 50%-80% van het app-geheugen voor Java-apps. Azure Spring Apps gebruikt met name de volgende instellingen:

  • Als het app-geheugen < 1 GB is, is de standaard maximale heapgrootte 50% van het app-geheugen.
  • Als 1 GB <= het app-geheugen < 2 GB is, is de standaard maximale heapgrootte 60% van het app-geheugen.
  • Als 2 GB <= het app-geheugen < 3 GB is, is de standaard maximale heapgrootte 70% van het app-geheugen.
  • Als 3 GB <= het app-geheugen is, is de standaard maximale heapgrootte 80% van het app-geheugen.

Standaard maximale grootte van direct geheugen

Wanneer de maximale directe geheugengrootte niet is ingesteld met behulp van JVM-opties, stelt de JVM automatisch de maximale directe geheugengrootte in op de waarde die wordt geretourneerd door Runtime.getRuntime.maxMemory(). Deze waarde is ongeveer gelijk aan de maximale heap-geheugengrootte. Zie het bestand JDK 8 VM.java voor meer informatie.

Indeling geheugengebruik

Heap-grootte wordt beïnvloed door uw doorvoer. In principe kunt u bij het configureren de standaard maximale heapgrootte behouden, wat redelijk geheugen voor andere onderdelen laat.

De grootte van de metaspace is afhankelijk van de complexiteit van uw code, zoals het aantal klassen.

De directe geheugengrootte is afhankelijk van uw doorvoer en uw gebruik van bibliotheken van derden, zoals nio en gzip.

In de volgende lijst wordt een typisch voorbeeld van een geheugenindeling voor apps van 2 GB beschreven. U kunt deze lijst raadplegen om de instellingen voor de geheugengrootte te configureren.

  • Totaal geheugen (2048M)
  • Heap-geheugen: Xmx is 1433,6M (70% van het totale geheugen). De referentiewaarde van het dagelijkse geheugengebruik is 1200M.
    • Jonge generatie
      • Overlevende ruimte (S0, S1)
      • Ruimte in Eden
    • Oude generatie
  • Geheugen zonder heap
    • Waargenomen deel (waargenomen door Spring Boot Actuator)
      • Metaspace: de referentiewaarde voor dagelijks gebruik is 50M-256M
      • Codecache
      • Gecomprimeerde klasruimte
    • Niet waargenomen deel (niet waargenomen door Spring Boot Actuator): de dagelijkse gebruiksreferentiewaarde is 150M-250M.
      • Threadstack
      • GC, intern symbool en andere
  • Direct geheugen: de referentiewaarde voor dagelijks gebruik is 10M-200M.

In het volgende diagram ziet u dezelfde informatie. Getallen in grijs zijn de referentiewaarden van het dagelijkse geheugengebruik.

Diagram van de typische geheugenindeling voor apps van 2 GB.

Over het algemeen moet u bij het configureren van maximale geheugengrootten rekening houden met het gebruik van elk onderdeel in het geheugen en de som van alle maximale grootten mag niet groter zijn dan het totale beschikbare geheugen.

Java OOM

OOM betekent dat de toepassing onvoldoende geheugen heeft. Er zijn twee verschillende concepten: container OOM en JVM OOM. Zie Problemen met opnieuw opstarten van apps die worden veroorzaakt door problemen met onvoldoende geheugen voor meer informatie.

Zie ook