SektionerRedigera
Det finns 10 grundläggande sektioner i Java-klassfilens struktur:
- Magiskt nummer: 0xCAFEBABE
- Version av klassfilens format: den mindre och större versionen av klassfilen
- Konstantpool: Pool av konstanter för klassen
- Access Flags: Till exempel om klassen är abstrakt, statisk etc.
- Denna klass: Namnet på den aktuella klassen
- Superklass: Namnet på superklassen
- Gränssnitt: Alla gränssnitt i klassen
- Fält: Alla fält i klassen
- Metoder: Alla fält i klassen
- Metoder: Alla metoder i klassen
- Attribut:
Magic NumberEdit
Klassfiler identifieras av följande 4 byte stora rubrik (hexadecimalt):
Magic NumberEdit
Klassfiler identifieras av följande 4 byte stora rubrik (hexadecimalt): CA FE BA BE
(de fyra första posterna i tabellen nedan). Historien om detta magiska nummer förklarades av James Gosling med hänvisning till en restaurang i Palo Alto:
”Vi brukade äta lunch på ett ställe som hette St Michael’s Alley. Enligt den lokala legenden brukade Grateful Dead i ett djupt mörkt förflutet uppträda där innan de blev stora. Det var ett ganska funky ställe som definitivt var ett Grateful Dead Kinda Place. När Jerry dog satte de till och med upp en liten buddhistliknande helgedom. När vi brukade gå dit kallade vi stället för Cafe Dead. Någonstans på vägen uppmärksammades det att detta var ett HEX-nummer. Jag höll på att omarbeta en del kod för filformat och behövde ett par magiska nummer: ett för den beständiga objektfilen och ett för klasser. Jag använde CAFEDEAD för objektfilformatet, och när jag letade efter hexord med fyra tecken som passade efter ”CAFE” (det verkade vara ett bra tema) stötte jag på BABE och bestämde mig för att använda det. vid den tidpunkten verkade det inte särskilt viktigt eller avsett att gå någon annanstans än i historiens soptunna. Så CAFEBABE blev klassfilformatet och CAFEDEAD blev formatet för beständiga objekt. Men den persistenta objektfaciliteten försvann, och med den försvann också användningen av CAFEDEAD – den ersattes så småningom av RMI.
General layoutEdit
Eftersom klassfilen innehåller objekt av varierande storlek och inte också innehåller inbäddade filoffsets (eller pekare), analyseras den vanligtvis sekventiellt, från den första byte mot slutet. På lägsta nivå beskrivs filformatet i termer av några grundläggande datatyper:
- u1: ett otecknat 8-bitars heltal
- u2: ett otecknat 16-bitars heltal i big-endian byteordning
- u4: ett otecknat 32-bitars heltal i big-endian byteordning
- tabell: en matris med objekt av varierande längd av någon typ. Antalet objekt i tabellen identifieras av ett föregående räknevärde (räknevärdet är en u2), men tabellens storlek i byte kan endast bestämmas genom att undersöka vart och ett av dess objekt.
Vissa av dessa grundläggande typer omtolkas sedan som värden på högre nivå (t.ex. strängar eller flyttal), beroende på sammanhanget.Det finns inget krav på ordjustering och därför används aldrig några utfyllnadsbytes.Den övergripande layouten för klassfilen visas i följande tabell.
byte offset | storlek | typ eller värde | beskrivning |
---|---|---|---|
0 | 4 bytes | u1 = 0xCA hex |
magiskt nummer (CAFEBABE) som används för att identifiera filen som överensstämmande med klassfilformatet |
1 | u1 = 0xFE hex |
||
2 | u1 = 0xBA hex |
||
3 | u1 = 0xBE hex |
||
4 | 2 bytes | u2 | minor versionsnummer på |
5 | |||
6 | 2 bytes | u2 | huvudversionsnummer för det klassfilformat som används.
Java SE 17 = 61 (0x3D hex), |
7 | |||
8 | 2 bytes | u2 | konstantpoolräkning, antal poster i följande konstantpooltabell. Detta antal är minst ett större än det faktiska antalet poster, se följande diskussion. |
9 | |||
10 | cpsize (variabel) | tabell | konstantpooltabell, en matris med poster i konstantpoolen av varierande storlek, som innehåller poster som bokstavliga tal, strängar och referenser till klasser eller metoder. Indexerad från och med 1, innehållande (constant pool count – 1) antal poster totalt (se anmärkning). |
… | |||
… | |||
… | |||
… | |||
10+cpsize | 2 bytes | u2 | access flags, en bitmask |
11+cpsize | |||
12+cpsize | 2 bytes | u2 | identifierar denna klass, index i konstantpoolen till en post av typen ”Class” |
13+cpsize | |||
14+cpsize | 2 bytes | u2 | identifierar superklass, index i konstantpoolen till en post av typen ”Class” |
15+cpsize | |||
16+cpsize | 2 bytes | u2 | interface count, antal poster i följande gränssnittstabell |
17+cpsize | |||
18+cpsize | isize (variabel) | table | interface table: En matris med variabel längd av konstanta poolindex som beskriver de gränssnitt som implementeras av den här klassen |
… | |||
… | |||
… | |||
18+cpsize+isize | 2 bytes | u2 | fältantal, Antal poster i följande fälttabell |
19+cpsize+isize | |||
20+cpsize+isize | fsize (variabel) | tabell | fälttabell, matris av fält med variabel längd
varje element är en field_info struktur definierad i https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.5 |
… | |||
… | |||
… | |||
20+cpsize+isize+fsize | 2 bytes | u2 | method count, antal poster i följande metodtabell |
21+cpsize+isize+fsize | |||
22+cpsize+isize+fsize | msize (variabel) | table | metodtabell, matris av metoder med variabel längd
varje element är en method_info struktur definierad i https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.6 |
… | |||
… | |||
… | |||
22+cpsize+isize+fsize+msize | 2 bytes | u2 | attributantal, Antal poster i följande attributtabell |
23+cpsize+isize+fsize+msize | |||
24+cpsize+isize+fsize+msize | asize (variabel) | table | attributtabell, matris av attribut med variabel längd
varje element är en attribut_informationsstruktur som definieras i https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7 |
… | |||
… | |||
… |
Representation i ett C-liknande programmeringsspråkRedigera
Då C inte har stöd för flera matriser med variabel längd inom en struct kommer koden nedan inte att kunna kompileras och tjänar endast som en demonstration.
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;}
KonstantpoolenEdit
I konstantpoolen lagras de flesta bokstavliga konstantvärden. Detta inkluderar värden som tal av alla slag, strängar, identifierarnamn, referenser till klasser och metoder samt typbeskrivningar. Alla index, eller referenser, till specifika konstanter i konstantpooltabellen ges av 16-bitarstal (typ u2), där indexvärde 1 hänvisar till den första konstanten i tabellen (indexvärde 0 är ogiltigt).
På grund av historiska val som gjordes under utvecklingen av filformatet är antalet konstanter i konstantpooltabellen i själva verket inte detsamma som det antal konstanter i konstantpoolen som föregår tabellen. För det första är tabellen indexerad med början vid 1 (i stället för 0), men räkningen ska egentligen tolkas som det maximala indexet plus ett. Dessutom tar två typer av konstanter (longs och doubles) upp två på varandra följande platser i tabellen, även om den andra sådana platsen är ett fantomindex som aldrig används direkt.
Typen av varje objekt (konstant) i konstantpoolen identifieras av en inledande byte-tagg. Det antal byte som följer efter denna tagg och deras tolkning är sedan beroende av taggvärdet. De giltiga konstanttyperna och deras taggvärden är:
Tag byte | Tillkommande byte | Beskrivning av konstant | Version införd |
---|---|---|---|
1 | 2+x byte (variabel) |
UTF-8 (Unicode) string: En teckensträng som föregås av ett 16-bitarstal (typ u2) som anger antalet bytes i den kodade strängen som följer omedelbart därefter (vilket kan vara annorlunda än antalet tecken). Observera att den kodning som används egentligen inte är UTF-8, utan innebär en liten modifiering av Unicodes standardkodningsform. | 1.0.2 |
3 | 4 bytes | Tal: ett signerat 32-bitars tvåkomplementtal i big-endian-format | 1.0.2 |
4 | 4 bytes | Float: ett 32-bitars IEEE 754 flyttal med enkel precision | 1.0.2 |
5 | 8 bytes | Lång: ett signerat 64-bitars tvåkomplementtal i big-endian-format (tar två platser i konstantpooltabellen) | 1.0.2 |
6 | 8 bytes | Double: ett 64-bitars dubbelprecisions IEEE 754 flyttal (tar två platser i konstantpoolsystemet) | 1.0.2 |
7 | 2 bytes | Klassreferens: ett index inom konstantpoolen till en UTF-8-sträng som innehåller det fullt kvalificerade klassnamnet (i internt format) (big-endian) | 1.0.2 |
8 | 2 bytes | Stringreferens: ett index inom konstantpoolen till en UTF-8-sträng (även big-endian) | 1.0.2 |
9 | 4 bytes | Fältreferens: två index inom konstantpoolen, det första pekar på en klassreferens, det andra på en deskriptor för namn och typ. (big-endian) | 1.0.2 |
10 | 4 bytes | Metodreferens: två index inom konstantpoolen, det första pekar på en klassreferens, det andra på en namn- och typbeskrivare. (big-endian) | 1.0.2 |
11 | 4 bytes | Interfacemetodreferens: två index inom konstantpoolen, det första pekar på en klassreferens, det andra på en namn- och typdeskriptor. (big-endian) | 1.0.2 |
12 | 4 bytes | Namn- och typdeskriptor: två index till UTF-8-strängar inom konstantpoolen, varav det första representerar ett namn (identifierare) och det andra en speciellt kodad typdeskriptor. | 1.0.2 |
15 | 3 bytes | Metodhandtag: Denna struktur används för att representera ett metodhandtag och består av en byte av typdeskriptor, följt av ett index inom konstantpoolen. | 7 |
16 | 2 bytes | Metodtyp: Denna struktur används för att representera en metodtyp och består av ett index inom konstantpoolen. | 7 |
17 | 4 bytes | Dynamisk: Denna struktur används för att ange en dynamiskt beräknad konstant som produceras genom anrop av en bootstrap-metod. | 11 |
18 | 4 bytes | InvokeDynamic: Detta används av en invokedynamic-instruktion för att specificera en bootstrap-metod, namnet på det dynamiska anropet, anropets argument- och returtyper och eventuellt en sekvens av ytterligare konstanter som kallas statiska argument till bootstrap-metoden. | 7 |
19 | 2 bytes | Modul: Detta används för att identifiera en modul. | 9 |
20 | 2 bytes | Paket: används för att identifiera ett paket som exporteras eller öppnas av en modul. | 9 |
Det finns endast två integrala konstanttyper, heltal och long. Andra integrala typer som förekommer i högnivåspråket, t.ex. boolean, byte och short måste representeras som en heltalskonstant.
Klassnamn i Java, när de är fullt kvalificerade, är traditionellt punktseparerade, t.ex. ”java.lang.Object”. I klassreferenskonstanter på låg nivå förekommer dock en intern form som istället använder snedstreck, t.ex. ”java/lang/Object”.
Unicode-strängarna, trots benämningen ”UTF-8-sträng”, kodas faktiskt inte enligt Unicode-standarden, även om den är likartad. Det finns två skillnader (se UTF-8 för en fullständig diskussion). Den första är att kodpunkten U+0000 kodas som två-byte-sekvensen C0 80
(i hex) i stället för standardkodningen med en enda byte 00
. Den andra skillnaden är att tilläggstecken (de som ligger utanför BMP vid U+10000 och högre) kodas med hjälp av en surrogatparkonstruktion som liknar UTF-16 i stället för att kodas direkt med UTF-8. I detta fall kodas var och en av de två surrogaten separat i UTF-8. Exempelvis kodas U+1D11E som 6-byte-sekvensen ED A0 B4 ED B4 9E
i stället för den korrekta 4-byte UTF-8-kodningen F0 9D 84 9E
.
.