Soubor třídy Java

SekceUpravit

Struktura souboru třídy Java obsahuje 10 základních sekcí:

  • Magické číslo: 0xCAFEBABE
  • Verze formátu souboru třídy: minoritní a majoritní verze souboru třídy
  • Fond konstant:
  • Příznaky přístupu: například zda je třída abstraktní, statická atd.
  • Tato třída: Název aktuální třídy
  • Super třída: Název nadřazené třídy
  • Rozhraní: Veškerá rozhraní ve třídě
  • Pole: Jakákoli pole ve třídě
  • Metody: Atributy: Jakékoli metody ve třídě
  • Atributy:

Magic NumberEdit

Soubory třídy se identifikují pomocí následující 4bajtové hlavičky (v šestnáctkové soustavě): CA FE BA BE (první 4 položky v tabulce níže). Historii tohoto magického čísla vysvětlil James Gosling s odkazem na restauraci v Palo Altu:

„Chodívali jsme na oběd do podniku, který se jmenoval Ulička svatého Michala. Podle místní legendy tam v hluboké temné minulosti vystupovali Grateful Dead, než se prosadili. Bylo to dost funky místo, které rozhodně patřilo Grateful Dead Kinda Place. Když Jerry zemřel, dokonce tam postavili malou buddhistickou svatyni. Když jsme tam chodili, říkali jsme tomu místu Cafe Dead. Někde v průběhu se zjistilo, že je to číslo HEX. Přepracovával jsem nějaký kód formátu souborů a potřeboval jsem pár magických čísel: jedno pro soubor trvalých objektů a jedno pro třídy. Pro formát objektového souboru jsem použil CAFEDEAD a při hledání čtyřznakových hexadecimálních slov, která se hodila za „CAFE“ (zdálo se to být dobré téma), jsem narazil na BABE a rozhodl se ho použít. v té době mi to nepřipadalo nijak strašně důležité ani předurčené k tomu, aby se dostalo někam jinam než do koše historie. A tak se CAFEBABE stalo formátem souborů tříd a CAFEDEAD formátem trvalých objektů. Ale zařízení pro trvalé objekty zaniklo a spolu s ním zaniklo i používání CAFEDEAD – nakonec bylo nahrazeno RMI.

Obecné rozloženíEdit

Protože soubor třídy obsahuje položky s proměnlivou velikostí a neobsahuje také vložené souborové offsety (nebo ukazatele), obvykle se analyzuje postupně, od prvního bajtu směrem ke konci. Na nejnižší úrovni je formát souboru popsán pomocí několika základních datových typů:

  • u1: celé 8bitové číslo bez znaménka
  • u2: celé 16bitové číslo bez znaménka v big-endiánském pořadí bajtů
  • u4: celé 32bitové číslo bez znaménka v big-endiánském pořadí bajtů
  • tabulka: pole položek proměnné délky nějakého typu. Počet položek v tabulce je identifikován předcházejícím číslem count (count je u2), ale velikost tabulky v bajtech lze určit pouze zkoumáním každé její položky.

Některé z těchto základních typů jsou pak v závislosti na kontextu reinterpretovány jako hodnoty vyšší úrovně (například řetězce nebo čísla s plovoucí desetinnou čárkou). není vynucováno zarovnání slov, a proto se nikdy nepoužívají žádné výplňové bajty. celkové uspořádání souboru třídy je uvedeno v následující tabulce.

byte offset size type or value description
0 4 bytes u1 =
0xCA hex
magické číslo (CAFEBABE) používané k identifikaci souboru jako odpovídajícího formátu souboru třídy
1 u1 =
0xFE hex
2 u1 =
0xBA hex
3 u1 =
0xBE hex
4 2 bajty u2 minimální číslo verze. použitý formát souboru třídy
5
6 2 bajty u2 hlavní číslo verze použitého formátu souboru třídy.

Java SE 17 = 61 (0x3D hex),
Java SE 16 = 60 (0x3C hex),
Java SE 15 = 59 (0x3B hex),
Java SE 14 = 58 (0x3A hex),
Java SE 13 = 57 (0x39 hex),
Java SE 12 = 56 (0x38 hex),
Java SE 11 = 55 (0x37 hex),
Java SE 10 = 54 (0x36 hex),
Java SE 9 = 53 (0x35 hex),
Java SE 8 = 52 (0x34 hex),
Java SE 7 = 51 (0x33 hex),
Java SE 6.0 = 50 (0x32 hex),
Java SE 5.0 = 49 (0x31 hex),
JDK 1.4 = 48 (0x30 hex),
JDK 1.3 = 47 (0x2F hex),
JDK 1.2 = 46 (0x2E hex),
JDK 1.1 = 45 (0x2D hex).
Podrobnosti o dřívějších číslech verzí viz poznámka pod čarou 1 v The JavaTM Virtual Machine Specification 2nd edition

7
8 2 bajty u2 počet konstant pool, počet položek v následující tabulce konstant pool. Tento počet je alespoň o jednu větší než skutečný počet položek; viz následující diskuse.
9
10 cpsize (proměnná) tabulka tabulka konstantního fondu, pole položek konstantního fondu proměnné velikosti, obsahující položky, jako jsou literální čísla, řetězce a odkazy na třídy nebo metody. Indexováno od 1, obsahuje (počet konstant pool – 1) počet položek celkem (viz poznámka).
10+cpsize 2 bajty u2 příznaky přístupu, bitová maska
11+cpsize
12+cpsize 2 bajty u2 identifikuje tuto třídu, index do fondu konstant na položku typu „Class“
13+cpsize
14+cpsize 2 bytes u2 identifikuje super třídu, index do fondu konstant na položku typu „Class“
15+cpsize
16+cpsize 2 byty u2 počet rozhraní, počet záznamů v následující tabulce rozhraní
17+cpsize
18+cpsize isize (proměnná) tabulka tabulka rozhraní: pole konstantních poolových indexů proměnné délky popisující rozhraní implementovaná touto třídou
18+cpsize+isize 2 bajty u2 počet polí, počet záznamů v následující tabulce polí
19+cpsize+isize
20+cpsize+isize fsize (proměnná) tabulka polí, pole proměnné délky

každý prvek je struktura field_info definovaná v https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.5

20+cpsize+isize+fsize 2 bajty u2 počet metod, počet záznamů v následující tabulce metod
21+cpsize+isize+fsize
22+cpsize+isize+fsize msize (proměnná) tabulka tabulka metod, pole metod proměnné délky

každý prvek je struktura method_info definovaná v https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.6

22+cpsize+isize+fsize+msize 2 bajty u2 počet atributů, počet záznamů v následující tabulce atributů
23+cpsize+isize+fsize+msize
24+cpsize+isize+fsize+msize asize (proměnná) tabulka atributů, pole atributů proměnné délky

každý prvek je struktura attribute_info definovaná v https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7

….

Reprezentace v programovacím jazyce podobném CEdit

Protože jazyk C nepodporuje vícenásobná pole proměnné délky v rámci struktury, níže uvedený kód se nezkompiluje a slouží pouze jako ukázka.

struct Class_File_Format { u4 magic_number; u2 minor_version; u2 major_version; u2 constant_pool_count; cp_info constant_pool; u2 access_flags; u2 this_class; u2 super_class; u2 interfaces_count; u2 interfaces; u2 fields_count; field_info fields; u2 methods_count; method_info methods; u2 attributes_count; attribute_info attributes;}

Bazén konstantEdit

Tabulka bazénu konstant je místem, kde je uložena většina literálních hodnot konstant. Patří sem hodnoty jako čísla všeho druhu, řetězce, názvy identifikátorů, odkazy na třídy a metody a deskriptory typů. Všechny indexy neboli odkazy na konkrétní konstanty v tabulce konstantního fondu jsou dány 16bitovými čísly (typ u2), kde hodnota indexu 1 odkazuje na první konstantu v tabulce (hodnota indexu 0 je neplatná).

Vzhledem k historickým volbám učiněným během vývoje formátu souboru není počet konstant v tabulce konstantního fondu ve skutečnosti stejný jako počet konstant, který tabulce předchází. Zaprvé, tabulka je indexována od 1 (nikoli od 0), ale počet by měl být ve skutečnosti interpretován jako maximální index plus jedna. Navíc dva typy konstant (longs a doubles) zabírají v tabulce dva po sobě jdoucí sloty, ačkoli druhý takový slot je fantomový index, který se nikdy přímo nepoužívá.

Typ každé položky (konstanty) v konstantním fondu je identifikován počáteční bytovou značkou. Počet bajtů následujících za touto značkou a jejich interpretace pak závisí na hodnotě značky. Platné typy konstant a jejich hodnoty tagů jsou:

Tag bajt Další bajty Popis konstanty Zavedená verze
1 2+x bajtů
(proměnná)
UTF-8 (Unicode) řetězec: řetězec znaků s předponou 16bitového čísla (typ u2) udávajícího počet bajtů v kódovaném řetězci, který bezprostředně následuje (může se lišit od počtu znaků). Všimněte si, že použité kódování není ve skutečnosti UTF-8, ale zahrnuje mírnou modifikaci standardního tvaru kódování Unicode. 1.0.2
3 4 bajty Integer: znaménkové 32bitové dvojkové doplňkové číslo ve formátu big-endian 1.0.2
4 4 bajty Float: 32bitové číslo s plovoucí desetinnou čárkou ve formátu IEEE 754 s jednou přesností 1.0.2
5 8 bajtů Long: 64bitové dvojkové číslo se znaménkem ve formátu big-endian (zabírá dvě místa v tabulce konstant) 1.0.2
6 8 bajtů Double: 64bitové číslo s plovoucí desetinnou čárkou ve formátu double-precision IEEE 754 (zabírá dva sloty v tabulce konstant) 1.0.2
7 2 bajty Odkaz na třídu: index v rámci fondu konstant na řetězec UTF-8 obsahující plně kvalifikovaný název třídy (v interním formátu) (big-endian) 1.0.2
8 2 bajty Odkaz na řetězec: index v rámci fondu konstant na řetězec UTF-8 (také v big-endian) 1.0.2
9 4 bajty Odkaz na pole: dva indexy v rámci fondu konstant, první ukazuje na odkaz na třídu, druhý na deskriptor jména a typu. (big-endian) 1.0.2
10 4 bajty Odkaz na metodu: dva indexy v rámci fondu konstant, první ukazuje na odkaz na třídu, druhý na deskriptor Name and Type. (big-endian) 1.0.2
11 4 bajty Odkaz na metodu rozhraní: dva indexy v rámci fondu konstant, první ukazuje na odkaz na třídu, druhý na deskriptor Name and Type. (big-endian) 1.0.2
12 4 bajty Deskriptor jména a typu: dva indexy na řetězce UTF-8 v rámci fondu konstant, první představuje jméno (identifikátor) a druhý speciálně kódovaný deskriptor typu. 1.0.2
15 3 bajty Ručka metody: tato struktura slouží k reprezentaci ručky metody a skládá se z jednoho bajtu deskriptoru typu, za kterým následuje index v rámci fondu konstant. 7
16 2 bajty Typ metody: tato struktura se používá k reprezentaci typu metody a skládá se z indexu v rámci fondu konstant. 7
17 4 bajty Dynamická: slouží k určení dynamicky vypočtené konstanty vytvořené voláním zaváděcí metody. 11
18 4 bajty InvokeDynamic: používá se instrukcí invokedynamic pro specifikaci zaváděcí metody, jména dynamického volání, argumentu a návratového typu volání a volitelně posloupnosti dalších konstant nazývaných statické argumenty zaváděcí metody. 7
19 2 bajty Modul: slouží k identifikaci modulu. 9
20 2 bajty Balíček: slouží k identifikaci balíčku exportovaného nebo otevřeného modulem. 9

Existují pouze dva integrální konstantní typy, integer a long. Ostatní integrální typy vyskytující se ve vysokoúrovňovém jazyce, jako jsou boolean, byte a short, musí být reprezentovány jako celočíselné konstanty.

Jména tříd v jazyce Java, pokud jsou plně kvalifikovaná, jsou tradičně oddělena tečkou, například „java.lang.Object“. V rámci nízkoúrovňových konstant odkazů na třídy se však objevuje vnitřní forma, která místo toho používá lomítka, například „java/lang/Object“.

Řetězce Unicode, navzdory přezdívce „řetězec UTF-8“, nejsou ve skutečnosti kódovány podle standardu Unicode, i když je to podobné. Existují dva rozdíly (kompletní diskusi naleznete v části UTF-8). Prvním je, že kódový bod U+0000 je kódován jako dvoubajtová sekvence C0 80 (v hexadecimálním tvaru) namísto standardního jednobajtového kódování 00. Druhý rozdíl spočívá v tom, že doplňkové znaky (ty, které jsou mimo BMP při U+10000 a výše) jsou kódovány pomocí konstrukce náhradních párů podobně jako UTF-16, místo aby byly přímo kódovány pomocí UTF-8. V tomto případě je každý ze dvou zástupných znaků kódován v UTF-8 samostatně. Například U+1D11E je kódováno jako 6bajtová sekvence ED A0 B4 ED B4 9E, nikoli jako správné 4bajtové kódování UTF-8 F0 9D 84 9E.

.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna.