boolean a boolean Rozloženie pamäte v JVM

1. Prehľad

V tomto rýchlom článku sa pozrieme, čo je to stopa a boolovský hodnotu v JVM za rôznych okolností.

Najskôr skontrolujeme JVM, aby sme videli veľkosti objektov. Potom pochopíme dôvody týchto veľkostí.

2. Inštalácia

Na kontrolu rozloženia pamäte objektov v JVM budeme vo veľkom rozsahu používať Java Object Layout (JOL). Preto musíme pridať veselé jadro závislosť:

 org.openjdk.jol jol-core 0,10 

3. Veľkosti predmetov

Ak požiadame JOL o vytlačenie podrobností VM z hľadiska veľkostí objektov:

System.out.println (VM.current (). Details ());

Keď sú komprimované odkazy povolené (predvolené správanie), zobrazí sa nám výstup:

# Spustenie 64-bitového HotSpot VM. # Používanie komprimovaného OOP s 3-bitovým posunom. # Používanie komprimovaného klassu s 3-bitovým posunom. # Objekty sú zarovnané na 8 bajtov. # Veľkosti polí podľa typu: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bajty] # Veľkosti prvkov poľa: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bajty ]

V prvých niekoľkých riadkoch vidíme niekoľko všeobecných informácií o VM. Potom sa dozvieme o veľkostiach objektov:

  • Referenčné dokumenty Java spotrebujú 4 bajty, boolovskýs /bajts sú 1 bajt, chars /krátkys sú 2 bajty, ints /plaváks sú 4 bajty a nakoniec dlhos /dvojitýs sú 8 bajtov
  • Tieto typy spotrebúvajú rovnaké množstvo pamäte, aj keď ich používame ako prvky poľa

Takže za prítomnosti komprimovaných odkazov boolovský hodnota trvá 1 bajt. Podobne každý boolovský v boolean [] spotrebuje 1 bajt. Vyrovnávacie výplne a hlavičky objektov však môžu zväčšiť priestor, ktorý spotrebuje boolovský a boolean [] ako uvidíme neskôr.

3.1. Žiadne komprimované odkazy

Aj keď deaktivujeme komprimované odkazy pomocou -XX: -UseCompressedOops, booleovská veľkosť sa vôbec nezmení:

# Veľkosti polí podľa typu: 8, 1, 1, 2, 2, 4, 4, 8, 8 [bajty] # Veľkosti prvkov poľa: 8, 1, 1, 2, 2, 4, 4, 8, 8 [bajty ]

Na druhej strane, referencie Java zaberajú dvojnásobok pamäte.

Takže napriek tomu, čo by sme najskôr mohli očakávať, booleans spotrebúvajú 1 bajt namiesto iba 1 bitu.

3.2. Roztrhanie slova

Vo väčšine architektúr neexistuje spôsob, ako získať prístup k jedinému bitu atómovo. Aj keby sme to chceli urobiť, pravdepodobne by sme pri aktualizácii iného skončili zápisom na susedné bity.

Jedným z cieľových zámerov JVM je zabrániť tomuto javu, známemu ako trhanie slov. To znamená, že v JVM by mal byť každý prvok poľa a poľa odlišný; aktualizácie jedného poľa alebo prvku nesmú interagovať s čítaním alebo aktualizáciami iného poľa alebo prvku.

Aby sme to zhrnuli, hlavnými dôvodmi sú problémy s adresnosťou a trhaním slov boolovskýsú viac ako iba jeden jediný bit.

4. Ukazovatele bežného objektu (OOP)

Teraz, keď už vieme boolovskýs sú 1 bajt, zvážme túto jednoduchú triedu:

class BooleanWrapper {private boolean value; }

Ak skontrolujeme rozloženie pamäte tejto triedy pomocou JOL:

System.out.println (ClassLayout.parseClass (BooleanWrapper.class) .toPrintable ());

Potom JOL vytlačí rozloženie pamäte:

 TYP ZMENY VEĽKOSTI POPIS HODNOTA 0 12 (hlavička objektu) N / A 12 1 boolean BooleanWrapper.value N / A 13 3 (strata v dôsledku ďalšieho zarovnania objektu) Veľkosť inštancie: 16 bajtov Straty priestoru: 0 bajtov interné + 3 bajty externé = 3 bajty spolu

The BooleanWrapper rozloženie pozostáva z:

  • 12 bajtov pre hlavičku, vrátane dvoch známka slová a jeden klass slovo. HotSpot JVM používa známka slovo na uloženie metaúdajov GC, hašovacieho kódu identity a informácií o uzamknutí. Používa tiež klass slovo na ukladanie metaúdajov triedy, napríklad kontroly typu za behu
  • 1 bajt pre skutočnú hodnotu boolovský hodnotu
  • 3 bajty výplne na účely zarovnania

V predvolenom nastavení by odkazy na objekty mali byť zarovnané o 8 bajtov. Preto JVM pridáva 3 bajty k 13 bajtom hlavičky a boolovský aby to bolo 16 bajtov.

Preto boolovský polia môžu kvôli zarovnaniu poľa spotrebovať viac pamäte.

4.1. Vlastné zarovnanie

Ak zmeníme hodnotu zarovnania na 32 pomocou -XX: ObjectAlignmentInBytes = 32, potom sa rovnaké rozloženie triedy zmení na:

TYP ZMENY VEĽKOSTI POPIS HODNOTA 0 12 (hlavička objektu) N / A 12 1 boolean BooleanWrapper.value N / A 13 19 (strata v dôsledku ďalšieho zarovnania objektu) Veľkosť inštancie: 32 bajtov Straty priestoru: 0 bajtov interné + 19 bajtov externé = 19 bajtov spolu

Ako je uvedené vyššie, JVM pridáva 19 bajtov výplne, aby sa veľkosť objektu stala násobkom 32.

5. Pole OOP

Pozrime sa, ako JVM ustanovuje a boolovský pole v pamäti:

boolean [] hodnota = nový boolean [3]; System.out.println (ClassLayout.parseInstance (hodnota) .toPrintable ());

Toto vytlačí rozloženie inštancie nasledovne:

POPIS TYPU VEĽKOSTI POSUNU 0 4 (hlavička objektu) # označiť slovo 4 4 (hlavička objektu) # označiť slovo 8 4 (hlavička objektu) # klass word 12 4 (hlavička objektu) # dĺžka poľa 16 3 boolean [Z. # [Z znamená booleovské pole 19 5 (strata v dôsledku ďalšieho zarovnania objektu)

Okrem dvoch známka slová a jeden klass slovo, ukazovatele poľa obsahujú ďalšie 4 bajty na uloženie ich dĺžok.

Pretože naše pole má tri prvky, veľkosť prvkov poľa je 3 bajty. Avšak tieto 3 bajty budú vyplnené 5 bajtmi zarovnania poľa, aby sa zabezpečilo správne zarovnanie.

Aj keď každý boolovský prvok v poli má iba 1 bajt, celé pole spotrebuje oveľa viac pamäte. Inými slovami, pri výpočte veľkosti poľa by sme mali brať do úvahy hlavičku a výplň.

6. Záver

V tomto rýchlom návode sme to videli boolovský polia spotrebúvajú 1 bajt. Dozvedeli sme sa tiež, že by sme mali brať do úvahy réžiu hlavičky a výplne vo veľkostiach objektov.

Pre podrobnejšiu diskusiu sa dôrazne odporúča skontrolovať sekciu oops zdrojového kódu JVM. Aleksey Shipilëv má v tejto oblasti tiež oveľa podrobnejší článok.

Ako obvykle sú všetky príklady dostupné na GitHub.


$config[zx-auto] not found$config[zx-overlay] not found