Java-luokkatiedosto

OsiotMuokkaa

Java-luokkatiedoston rakenteessa on 10 perusosiota:

  • Taikanumero: 0xCAFEBABE
  • Luokkatiedoston formaatin versio: luokkatiedoston minor- ja major-versiot
  • Konstanttipooli: Pool of constants for the class
  • Access Flags: esimerkiksi onko luokka abstrakti, staattinen jne.
  • This Class: Nykyisen luokan nimi
  • Super Class: Super-luokan nimi
  • Rajapinnat: Luokan mahdolliset rajapinnat
  • Kentät: Kaikki luokan kentät
  • Metodit: Kaikki luokan metodit
  • Attribuutit: Luokan mahdolliset attribuutit (esim. lähdetiedoston nimi jne.)

Magic NumberEdit

Luokkatiedostot tunnistetaan seuraavalla 4 tavun otsikolla (heksadesimaalisessa muodossa): CA FE BA BE (neljä ensimmäistä merkintää alla olevassa taulukossa). Tämän maagisen numeron historian selitti James Gosling viitaten ravintolaan Palo Altossa:

”Meillä oli tapana käydä lounaalla paikassa nimeltä St Michael’s Alley. Paikallisen legendan mukaan syvällä pimeässä menneisyydessä Grateful Dead esiintyi siellä ennen kuin se nousi suureksi. Se oli aika funky paikka, joka oli ehdottomasti Grateful Dead Kinda Place. Kun Jerry kuoli, sinne pystytettiin jopa pieni buddhalainen pyhäkkö. Kun kävimme siellä, kutsuimme paikkaa Cafe Deadiksi. Jossain vaiheessa huomattiin, että kyseessä oli HEX-numero. Olin uudistamassa tiedostomuotokoodia ja tarvitsin pari taikanumeroa: yhden pysyvää objektitiedostoa varten ja yhden luokkia varten. Käytin CAFEDEADia objektitiedoston muotoa varten, ja etsiessäni 4-merkkisiä heksasanoja, jotka sopivat ”CAFE”:n jälkeen (se tuntui olevan hyvä teema), törmäsin BABEen ja päätin käyttää sitä. tuolloin se ei tuntunut kauhean tärkeältä eikä sen kohtalona ollut mennä minnekään muualle kuin historian roskakoriin. Niinpä CAFEBABEsta tuli luokkatiedostomuoto ja CAFEDEADista pysyvien objektien muoto. Mutta pysyvien objektien mahdollisuus hävisi, ja sen mukana hävisi myös CAFEDEADin käyttö – se korvattiin lopulta RMI:llä.

Yleinen ulkoasuEdit

Koska luokkatiedosto sisältää vaihtelevan kokoisia kohteita eikä se sisällä myös upotettuja tiedostooffsetteja (tai osoittimia), se jäsennetään tyypillisesti peräkkäin, ensimmäisestä tavusta kohti loppua. Alimmalla tasolla tiedostomuoto kuvataan muutaman perustavanlaatuisen tietotyypin avulla:

  • u1: 8-bittinen ennenmerkitsematon kokonaisluku
  • u2: 16-bittinen ennenmerkitsematon kokonaisluku big-endiaanisessa tavujärjestyksessä
  • u4: 32-bittinen ennenmerkitsematon kokonaisluku big-endiaanisessa tavujärjestyksessä
  • taulukko (table): Joukko (array) vaihtelevan pituisia elementtejä jostakin tyypistä. Taulukon kohteiden lukumäärä tunnistetaan sitä edeltävällä laskentanumerolla (laskentanumero on u2), mutta taulukon koko tavuina voidaan määrittää vain tarkastelemalla kutakin sen kohdetta.

Joitakin näistä perustyypeistä tulkitaan sitten uudelleen korkeamman tason arvoiksi (kuten merkkijonoiksi tai liukuluvuiksi) asiayhteydestä riippuen.Sanakohdistusta (word alignment) ei pakoteta noudattamaan, joten pehmustustavaroita ei käytetä.Luokkatiedoston yleinen ulkoasu on seuraavassa taulukossa esitetyn mukainen.

tavun siirto koko tyyppi tai arvo kuvaus
0 4 tavua u1 =
0xCA hex
maaginen numero (CAFEBABE), jolla tiedosto tunnistetaan luokkatiedostomuodon mukaiseksi
1 u1 =
0xFE hex
2 u1 =
0xBA hex
3 u1 =
0xBE hex
4 2 tavua u2 miinusversioluku käytettävä luokkatiedostomuoto
5
6 2 tavua u2 käytettävän luokkatiedostomuodon pääversionumero.

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).
Tietoja aikaisemmista versionumeroista on alaviitteessä 1 osoitteessa The JavaTM Virtual Machine Specification 2nd edition

7
8 2 tavua u2 konstanttipoolien lukumäärän määrä, merkintöjen määrä seuraavassa vakiopoolien taulukossa. Tämä luku on vähintään yhden verran suurempi kuin merkintöjen todellinen määrä; ks. seuraava keskustelu.
9
10 cpsize (muuttuja) taulukko constant pool -taulukko, vaihtelevan kokoisten constant pool -merkintöjen matriisi, joka sisältää elementtejä, kuten literaalisia numeroita, merkkijonoja ja viittauksia luokkiin tai menetelmiin. Indeksoitu alkaen 1:stä, sisältää (constant pool count – 1) merkintöjen kokonaismäärän (katso huomautus).
10+cpsize 2 tavua u2 access flags, bittimerkki
11+cpsize
12+cpsize 2 tavua u2 identifioi tämän luokan, indeksi vakioaltaan ”Class”-tyyppiseen merkintään
13+cpsize
14+cpsize 2 tavua u2 identifioi superluokan, indeksi vakioaltaan ”Class”-tyyppiseen merkintään
15+cpsize
16+cpsize 2 tavua u2 liitännän määrä, merkintöjen määrä seuraavassa rajapintataulussa
17+cpsize
18+cpsize isize (muuttuja) table interface table: muuttujapituinen joukko vakiopooliindeksejä, jotka kuvaavat tämän luokan toteuttamia rajapintoja
18+cpsize+isize 2 tavua u2 field count, merkintöjen lukumäärä seuraavassa kenttätaulukossa
19+cpsize+isize
20+cpsize+isize fsize (muuttuja) taulukko kenttätaulukko, muuttujan pituinen kenttien joukko

jokainen elementti on kohdassa https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.5

määritelty field_info -rakenne…
20+cpsize+isize+fsize 2 tavua u2 method count, merkintöjen lukumäärä seuraavassa metoditaulukossa
21+cpsize+isize+fsize
22+cpsize+isize+fsize msize (muuttuja) taulukko metoditaulukko, muuttujan pituinen joukko metodeja

jokainen elementti on https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.6

:ssä määritelty method_info rakenne…
22+cpsize+isize+fsize+msize 2 tavua u2 attribuuttien määrä, merkintöjen määrä seuraavassa attribuuttitaulukossa
23+cpsize+isize+fsize+msize
24+cpsize+isize+fsize+msize asize (muuttuja) taulukko attribuuttitaulukko, muuttujan pituinen attribuuttien joukko

jokainen elementti on attribute_info -rakenne, joka on määritelty kohdassa https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7

Esitys C:n kaltaisella ohjelmointikielelläMuokkaa

Sen vuoksi, että C ei tue useita muuttuvan pituisia matriiseja yhden structin sisällä, alla oleva koodi ei käänny, ja se toimii vain demonstraationa.

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;}

VakiopooliEdit

Vakiopooli-taulukkoon tallennetaan suurin osa literaalisista vakioarvoista. Siihen kuuluvat sellaiset arvot kuin kaikenlaiset numerot, merkkijonot, tunnistenimet, viittaukset luokkiin ja metodeihin sekä tyyppikuvaajat. Kaikki indeksit eli viittaukset tiettyihin vakioihin vakiopoolitaulukossa annetaan 16-bittisinä (tyyppi u2) numeroina, joissa indeksiarvo 1 viittaa taulukon ensimmäiseen vakioon (indeksiarvo 0 on mitätön).

Tiedostomuodon kehityksessä tehtyjen historiallisten valintojen vuoksi vakioiden määrä vakiopoolitaulukossa ei todellisuudessa ole sama kuin taulukon edessä oleva vakiopoolin määrä. Ensinnäkin taulukko on indeksoitu alkaen 1:stä (eikä 0:sta), mutta lukumäärää pitäisi itse asiassa tulkita enimmäisindeksiksi plus yksi. Lisäksi kaksi vakiotyyppiä (longit ja doublet) vievät taulukossa kaksi peräkkäistä paikkaa, vaikka toinen tällainen paikka on näennäisindeksi, jota ei koskaan suoraan käytetä.

Kunkin vakiopoolin kohteen (vakion) tyyppi tunnistetaan alkutunnisteen avulla. Tämän tunnisteen jälkeisten tavujen määrä ja niiden tulkinta riippuvat tunnisteen arvosta. Kelvolliset vakiotyypit ja niiden tag-arvot ovat:

Tag-tavu Lisätavut Vakion kuvaus Version käyttöönotto
1 2+x tavua
(muuttuja)
UTF-8-merkkijono UTF-8-merkkijono: merkkijono, jonka etuliitteenä on 16-bittinen luku (tyyppi u2), joka ilmaisee välittömästi seuraavan koodatun merkkijonon tavujen lukumäärän (joka voi olla eri kuin merkkien lukumäärä). Huomaa, että käytetty koodaus ei ole varsinaisesti UTF-8, vaan kyseessä on Unicode-standardin koodausmuodon lievä muokkaus. 1.0.2
3 4 tavua Integer: merkkipitoinen 32-bittinen kaksikomplementtiluku big-endian-muodossa 1.0.2
4 4 tavua Float: 32-bittinen yhden tarkkuuden IEEE 754 -liukuluku liukuluvulla 1.0.2
5 8 tavua Long: Merkitty 64-bittinen kaksoiskomplementtiluku big-endian-muodossa (vie kaksi paikkaa vakiolukutaulukossa) 1.0.2
6 8 tavua Double: 64-bittinen kaksoistarkkuuden IEEE 754 -liukuluku (vie kaksi paikkaa vakiopoolitaulukossa) 1.0.2
7 2 tavua Luokkaviittaus: vakioaltaan sisällä oleva indeksi UTF-8-merkkijonoon, joka sisältää täysin määritellyn luokan nimen (sisäisessä muodossa) (big-endian) 1.0.2
8 2 tavua String-viittaus: indeksi UTF-8-merkkijonoon (myös big-endian) 1.0.2
9 4 tavua Kenttäviittaus: kaksi indeksiä vakiopoolin sisällä, joista ensimmäinen osoittaa luokkaviittaukseen ja toinen Name and Type -kuvaajaan. (big-endian) 1.0.2
10 4 tavua Menetelmäviittaus: kaksi indeksiä vakiopoolin sisällä, joista ensimmäinen osoittaa luokkaviittaukseen, toinen Name and Type -kuvaajaan. (big-endian) 1.0.2
11 4 tavua Liitännäismenetelmäviittaus: kaksi indeksiä vakiopoolin sisällä, joista ensimmäinen osoittaa luokkaviittaukseen, toinen Name and Type -kuvaajaan. (big-endian) 1.0.2
12 4 tavua Nimi- ja tyyppikuvaaja: kaksi indeksiä vakioaltaan sisällä oleviin UTF-8-merkkijonoihin, joista ensimmäinen viittaa nimeen (tunnisteeseen) ja toinen erikoiskoodattuun tyyppikuvaajaan. 1.0.2
15 3 tavua Metodin kahva: Tätä rakennetta käytetään metodin kahvan esittämiseen, ja se koostuu yhdestä tavusta tyypin kuvaajaa, jota seuraa indeksi vakioaltaan sisällä. 7
16 2 tavua Metodin tyyppi: Tätä rakennetta käytetään metodin tyypin esittämiseen, ja se koostuu indeksistä vakioaltaan sisällä. 7
17 4 tavua Dynaaminen: tätä käytetään määrittelemään dynaamisesti laskettu vakio, joka tuotetaan kutsumalla käynnistysmetodia. 11
18 4 tavua InvokeDynamic: tätä käytetään invokedynamic-käskyssä määrittämään bootstrap-metodi, dynaamisen kutsun nimi, kutsun argumentti- ja paluutyypit sekä valinnaisesti bootstrap-metodin staattisiksi argumenteiksi kutsuttujen lisävakioiden sarja. 7
19 2 tavua Moduuli: Tätä käytetään moduulin tunnistamiseen. 9
20 2 tavua Paketti: tätä käytetään tunnistamaan moduulin viemä tai avaama paketti. 9

On vain kaksi integraalista vakiotyyppiä, kokonaisluku ja pitkä. Muut korkean tason kielessä esiintyvät integraalityypit, kuten boolean, byte ja short, on esitettävä kokonaislukuvakioina.

Luokkien nimet Javassa, kun ne ovat täysin päteviä, ovat perinteisesti piste-erotettuja, kuten ”java.lang.Object”. Matalan tason luokkaviitevakioiden sisällä esiintyy kuitenkin sisäinen muoto, jossa käytetään sen sijaan vinoviivoja, kuten ”java/lang/Object”.

Unicode-merkkijonoja ei nimimerkistä ”UTF-8-merkkijono” huolimatta itse asiassa koodata Unicode-standardin mukaisesti, vaikka se onkin samankaltainen. Niissä on kaksi eroa (ks. UTF-8, jossa on kattava keskustelu). Ensimmäinen on se, että koodipiste U+0000 on koodattu kahden tavun sarjana C0 80 (heksadesimaalina) standardin yhden tavun koodauksen 00 sijasta. Toinen ero on se, että lisämerkit (BMP:n ulkopuolella olevat merkit U+10000:ssa ja sen yläpuolella) koodataan UTF-16:n kaltaisella korvaavalla parirakenteella sen sijaan, että ne koodattaisiin suoraan UTF-8:lla. Tällöin kumpikin kahdesta sijaismerkistä koodataan UTF-8:ssa erikseen. Esimerkiksi U+1D11E koodataan 6 tavun sarjana ED A0 B4 ED B4 9E, eikä oikeana 4 tavun UTF-8-koodauksena F0 9D 84 9E.

.

Vastaa

Sähköpostiosoitettasi ei julkaista.