Java-klassfil

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),
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).
För detaljer om tidigare versionsnummer se fotnot 1 i The JavaTM Virtual Machine Specification 2nd edition

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.

.

Lämna ett svar

Din e-postadress kommer inte publiceras.