Sdílet prostřednictvím


Správa paměti v Javě

Poznámka:

Azure Spring Apps je nový název služby Azure Spring Cloud. Přestože má služba nový název, na některých místech uvidíte starý název, protože pracujeme na aktualizaci prostředků, jako jsou snímky obrazovky, videa a diagramy.

Tento článek se vztahuje na: ✔️ Basic/Standard ✔️ Enterprise

Tento článek popisuje různé koncepty související se správou paměti Java, které vám pomůžou pochopit chování aplikací v Javě hostovaných v Azure Spring Apps.

Model paměti Java

Paměť aplikace v Javě má několik částí a existují různé způsoby rozdělení částí. Tento článek popisuje paměť Javy rozdělenou do paměti haldy, paměti bez haldy a přímé paměti.

Paměť haldy

Paměť haldy ukládá všechny instance a pole tříd. Každý virtuální počítač Java (JVM) má pouze jednu oblast haldy, která se sdílí mezi vlákny.

Ovladač Spring Boot může sledovat hodnotu paměti haldy. Spring Boot Poháněcího zařízení přebírá hodnotu haldy jako součást jvm.memory.used/committed/max. Další informace najdete v části jvm.memory.used/committed/max v nástrojích pro řešení problémů s pamětí.

Paměť haldy je rozdělena na mladou generaci a starou generaci. Tyto termíny jsou popsány v následujícím seznamu spolu se souvisejícími termíny.

  • Mladá generace: všechny nové objekty jsou přiděleny a ve věku mladé generace.

    • Eden prostor: nové objekty jsou přiděleny v Eden prostoru.
    • Přeživší prostor: objekty se přesunou z Edenu do prostoru přeživšího po přežití jednoho cyklu uvolňování paměti. Přeživší prostor lze rozdělit na dvě části: s1 a s2.
  • Stará generace: označuje se také jako tenured prostor. Objekty, které zůstaly v přeživších prostorech po dlouhou dobu, budou přesunuty do staré generace.

Před Javou 8 byla také součástí haldy další oddíl s názvem trvalé generování . Od Javy 8 se trvalé generování nahradilo metaprostorem v paměti bez haldy.

Paměť bez haldy

Paměť bez haldy je rozdělena do následujících částí:

  • Část paměti bez haldy, která nahradila trvalou generaci (nebo permGen) počínaje Javou 8. Spring Boot Poháněcí zařízení sleduje tuto část a bere ji jako součást jvm.memory.used/committed/max. Jinými slovy, jvm.memory.used/committed/max je součet paměti haldy a bývalý permGen část paměti bez haldy. Bývalá trvalá generace se skládá z následujících částí:

    • Metaspace, který ukládá definice tříd načtené zavaděči tříd.
    • Komprimovaný prostor třídy, který je určen pro komprimované ukazatele třídy.
    • Mezipaměť kódu, která ukládá nativní kód zkompilovaný JIT.
  • Jiná paměť, jako je zásobník vláken, který není pozorován pomocí ovladače Spring Boot.

Přímá paměť

Přímá paměť je nativní paměť přidělena java.nio.DirectByteBuffer, která se používá v knihovnách třetích stran, jako je nio a gzip.

Poháněcího zařízení Spring Boot není pozorována hodnota přímé paměti.

Následující diagram shrnuje model paměti Java popsaný v předchozí části.

Diagram znázorňující model paměti Java

Uvolňování paměti Jazyka Java

Existují tři termíny týkající se uvolňování paměti Java (GC): "Minor GC", "Major GC" a "Full GC". Tyto termíny nejsou jasně definovány ve specifikaci prostředí JVM. Tady považujeme za ekvivalentní hlavní uvolňování paměti a úplné uvolňování paměti.

Menší uvolňování paměti se provádí, když je eden prostor plný. Odstraní všechny mrtvé objekty v mladé generaci a přesune živé objekty z Eden prostoru do s1 přeživšího prostoru nebo od s1 do s2.

Úplné uvolňování paměti nebo hlavní uvolňování paměti v celé haldě. Full GC může také shromažďovat části, jako je metaprostor a přímá paměť, které lze vyčistit pouze úplným uvolňováním paměti.

Maximální velikost haldy ovlivňuje frekvenci menšího uvolňování paměti a plného uvolňování paměti. Maximální metaprostor a maximální velikost přímé paměti ovlivňují plné uvolňování paměti.

Když nastavíte maximální velikost haldy na nižší hodnotu, dochází k uvolňování paměti častěji, což aplikaci trochu zpomaluje, ale lépe omezuje využití paměti. Když nastavíte maximální velikost haldy na vyšší hodnotu, dochází k uvolňování paměti méně často, což může způsobit větší riziko nedostatku paměti (OOM). Další informace najdete v části Typy problémů s nedostatkem paměti při restartování aplikace způsobené problémy s nedostatkem paměti.

Metaprostor a přímá paměť lze shromažďovat pouze úplným uvolňováním paměti. Pokud je metaprostor nebo přímá paměť plná, dojde k úplnému uvolňování paměti.

Konfigurace paměti Java

Následující části popisují důležité aspekty konfigurace paměti Java.

Kontejnerizace Java

Aplikace v Azure Spring Apps běží v kontejnerových prostředích. Další informace najdete v tématu Kontejnerizace aplikací v Javě.

Důležité možnosti prostředí JVM

Maximální velikost každé části paměti můžete nakonfigurovat pomocí možností prostředí JVM. Možnosti prostředí JVM můžete nastavit pomocí příkazů Azure CLI nebo webu Azure Portal. Další informace najdete v části Upravit konfigurace a opravit problémy nástroje pro řešení problémů s pamětí.

Následující seznam popisuje možnosti prostředí JVM:

  • Konfigurace velikosti haldy

    • -Xms nastaví počáteční velikost haldy absolutní hodnotou.
    • -Xmx nastaví maximální velikost haldy absolutní hodnotou.
    • -XX:InitialRAMPercentage nastaví počáteční velikost haldy o procento velikosti haldy / velikosti paměti aplikace.
    • -XX:MaxRAMPercentage nastaví maximální velikost haldy o procento velikosti haldy nebo velikosti paměti aplikace.
  • Konfigurace přímé velikosti paměti

    • -XX:MaxDirectMemorySize nastaví maximální velikost přímé paměti absolutní hodnotou. Další informace naleznete v tématu MaxDirectMemorySize v dokumentaci Oracle.
  • Konfigurace velikosti metaprostoru

    • -XX:MaxMetaspaceSize nastaví maximální velikost metaprostoru absolutní hodnotou.

Výchozí maximální velikost paměti

Následující části popisují, jak jsou nastaveny výchozí maximální velikosti paměti.

Výchozí maximální velikost haldy

Azure Spring Apps nastaví výchozí maximální velikost paměti haldy na přibližně 50 –80 % paměti aplikace pro aplikace v Javě. Konkrétně Azure Spring Apps používá následující nastavení:

  • Pokud paměť < aplikace 1 GB, bude výchozí maximální velikost haldy 50 % paměti aplikace.
  • Pokud 1 GB <= paměť < aplikace 2 GB, bude výchozí maximální velikost haldy 60 % paměti aplikace.
  • Pokud 2 GB <= paměť < aplikace 3 GB, výchozí maximální velikost haldy bude 70 % paměti aplikace.
  • Pokud 3 GB <= paměť aplikace, výchozí maximální velikost haldy bude 80 % paměti aplikace.

Výchozí maximální velikost přímé paměti

Pokud maximální velikost přímé paměti není nastavena pomocí možností JVM, JVM automaticky nastaví maximální přímou velikost paměti na hodnotu vrácenou modulem Runtime.getRuntime.maxMemory(). Tato hodnota se přibližně rovná maximální velikosti paměti haldy. Další informace naleznete v souboru JDK 8 VM.java.

Rozložení využití paměti

Velikost haldy má vliv na propustnost. V podstatě při konfiguraci můžete zachovat výchozí maximální velikost haldy, která ponechá přiměřenou paměť pro jiné části.

Velikost metaprostoru závisí na složitosti kódu, například počtu tříd.

Velikost přímé paměti závisí na propustnosti a použití knihoven třetích stran, jako je nio a gzip.

Následující seznam popisuje typickou ukázku rozložení paměti pro 2 GB aplikací. V tomto seznamu můžete nakonfigurovat nastavení velikosti paměti.

  • Celková paměť (2048 M)
  • Paměť haldy: Xmx je 1433,6M (70 % celkové paměti). Referenční hodnota denního využití paměti je 1200 M.
    • Mladá generace
      • Přeživší prostor (S0, S1)
      • Eden space
    • Stará generace
  • Paměť bez haldy
    • Pozorovaná část (pohyblivým ovladačem Spring Boot)
      • Metaspace: Referenční hodnota denního využití je 50M–256M
      • Mezipaměť kódu
      • Komprimovaný prostor třídy
    • Nepozorovaná část (nepozorovaná ovladačem Spring Boot): Referenční hodnota denního využití je 150M-250M.
      • Zásobník vláken
      • GC, vnitřní symbol a další
  • Přímá paměť: Referenční hodnota denního využití je 10M–200M.

Následující diagram znázorňuje stejné informace. Šedá čísla jsou referenčními hodnotami denního využití paměti.

Diagram typického rozložení paměti pro 2 GB aplikací

Celkově byste při konfiguraci maximální velikosti paměti měli zvážit využití každé části paměti a součet všech maximálních velikostí by neměl překročit celkovou dostupnou paměť.

Java OOM

OOM znamená, že aplikace není v paměti. Existují dva různé koncepty: kontejner OOM a OOM JVM. Další informace najdete v tématu Problémy s restartováním aplikace způsobené problémy s nedostatkem paměti.

Viz také