Java-klassefil

SektionerRediger

Der er 10 grundlæggende sektioner i Java-klassefilens struktur:

  • Magisk nummer: 0xCAFEBABE
  • Version af klassefilformatet: de mindre og større versioner af klassefilen
  • Konstantpulje: Pool af konstanter for klassen
  • Adgangsflag: F.eks. om klassen er abstrakt, statisk osv.
  • Denne klasse: Navnet på den aktuelle klasse
  • Superklasse: Denne klasse: Navnet på superklassen
  • Interfaces: Navnet på den aktuelle klasse: Eventuelle grænseflader i klassen
  • Fields: Fields: Alle felter i klassen
  • Metoder: Alle felter i klassen
  • Metoder: Alle metoder i klassen
  • Attributter: Alle metoder i klassen
  • Attributter: Alle attributter for klassen (f.eks. navnet på kildefilen osv.)

Magic NumberEdit

Klassefiler identificeres ved følgende 4 bytes header (i hexadecimalt format): CA FE BA BE (de første 4 poster i nedenstående tabel). Historien om dette magiske tal blev forklaret af James Gosling med henvisning til en restaurant i Palo Alto:

“Vi plejede at gå til frokost på et sted, der hed St Michael’s Alley. Ifølge den lokale legende plejede Grateful Dead i en dyb mørk fortid at optræde der, før de blev store. Det var et ret funky sted, som helt sikkert var et Grateful Dead-agtigt sted. Da Jerry døde, opstillede de endda en lille buddhistisk helligdom. Når vi plejede at gå der, kaldte vi stedet for Cafe Dead. Et eller andet sted på et tidspunkt blev det bemærket, at det var et HEX-nummer. Jeg var i gang med at omarbejde noget filformatkode og havde brug for et par magiske tal: et til den vedvarende objektfil og et til klasser. Jeg brugte CAFEDEAD til objektfilformatet, og da jeg søgte efter hex-ord med 4 tegn, der passede efter “CAFE” (det virkede som et godt tema), fandt jeg BABE og besluttede mig for at bruge det, og på det tidspunkt virkede det ikke særlig vigtigt eller bestemt til at gå andre steder hen end i historiens skraldespand. Så CAFEBABE blev klassefilformatet, og CAFEDEAD blev det vedvarende objektformat. Men den persistente objektfacilitet forsvandt, og med den forsvandt også brugen af CAFEDEAD – den blev til sidst erstattet af RMI.

Generelt layoutEdit

Da klassefilen indeholder elementer af variabel størrelse og ikke også indeholder indlejrede filoffsets (eller pointere), analyseres den typisk sekventielt, fra den første byte mod slutningen. På det laveste niveau beskrives filformatet i form af nogle få grundlæggende datatyper:

  • u1: et 8-bit heltal uden fortegn
  • u2: et 16-bit heltal uden fortegn i big-endian byteorden
  • u4: et 32-bit heltal uden fortegn i big-endian byteorden
  • tabel: et array af elementer af variabel længde af en eller anden type. Antallet af elementer i tabellen identificeres ved et forudgående tælletal (tallet er et u2), men tabellens størrelse i byte kan kun bestemmes ved at undersøge hvert af dens elementer.

Nogle af disse grundlæggende typer omfortolkes derefter som værdier på højere niveau (f.eks. strenge eller flydende tal), afhængigt af konteksten.Der er ingen håndhævelse af ordjustering, og der anvendes derfor aldrig nogen padding-bytes.Det overordnede layout af klassefilen er som vist i følgende tabel.

byte offset størrelse type eller værdi beskrivelse
0 4 bytes u1 =
0xCA hex
magisk tal (CAFEBABE), der anvendes til at identificere filen som værende i overensstemmelse med klassefilformatet
1 u1 =
0xFE hex
2 u1 =
0xBA hex
3 u1 =
0xBE hex
4 2 bytes u2 minor versionsnummer af den klassefilformat, der anvendes
5
6 2 bytes u2 major versionsnummer for det klassefilformat, der anvendes.

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).For oplysninger om tidligere versionsnumre se fodnote 1 i The JavaTM Virtual Machine Specification 2nd edition

7
8 2 bytes u2 konstant pool count, antal poster i følgende konstant pool-tabelle. Dette antal er mindst én større end det faktiske antal poster; se følgende diskussion.
9
10 cpsize (variabel) tabel konstant puljetabel, et array af poster i konstantpuljen af variabel størrelse, der indeholder elementer såsom bogstavelige tal, strenge og referencer til klasser eller metoder. Indekseret fra 1, indekseret fra 1, indeholdende (konstant pool count – 1) antal poster i alt (se note).
10+cpsize 2 bytes u2 access flags, en bitmaske
11+cpsize
12+cpsize 2 bytes u2 identificerer denne klasse, indeks i konstantpuljen til en post af typen “Class”
13+cpsize
14+cpsize 2 bytes u2 identificerer superklassen, indeks i konstantpuljen til en post af “Class”-typen
15+cpsize
16+cpsize 2 bytes u2 interface count, antal poster i følgende grænsefladetabel
17+cpsize
18+cpsize isize (variabel) table interfacetabel: et array af variabel længde med konstante puljeindekser, der beskriver de grænseflader, der er implementeret af denne klasse
18+cpsize+isize 2 bytes u2 felt antal, antal poster i følgende felttabel
19+cpsize+isize
20+cpsize+isize fsize (variabel) tabel felttabel , array af felter af variabel længde

hvert element er en field_info struktur defineret i https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.5

20+cpsize+isize+fsize 2 bytes u2 metode count, antal poster i følgende metodetabel
21+cpsize+isize+fsize
22+cpsize+isize+fsize msize (variabel) table metodetabel, array af metoder af variabel længde

hvert element er en method_info struktur defineret i https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.6

22+cpsize+isize+fsize+msize 2 bytes u2 atribute count, antal poster i følgende attributtabel
23+cpsize+isize+fsize+msize
24+cpsize+isize+fsize+msize asize (variabel) table attributtabel, array af attributter med variabel længde

hvert element er en attribut_informationsstruktur defineret i https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7

Repræsentation i et C-lignende programmeringssprogRediger

Da C ikke understøtter flere arrays af variabel længde inden for en struct, vil nedenstående kode ikke kunne kompileres og tjener kun som 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;}

KonstantpuljenRediger

Konstantpuljen er det sted, hvor de fleste bogstavelige konstante værdier er gemt. Dette omfatter værdier som tal af alle slags, strenge, identifikatornavne, referencer til klasser og metoder samt typebeskrivelser. Alle indekser, eller referencer, til specifikke konstanter i konstantpuljetabellen angives ved hjælp af 16-bit (type u2) tal, hvor indeksværdi 1 henviser til den første konstant i tabellen (indeksværdi 0 er ugyldig).

På grund af historiske valg, der blev truffet under udviklingen af filformatet, er antallet af konstanter i konstantpuljetabellen faktisk ikke det samme som antallet af konstanter i konstantpuljetabellen, der går forud for tabellen. For det første er tabellen indekseret fra 1 (i stedet for 0), men tallet skal faktisk fortolkes som det maksimale indeks plus et. Desuden optager to typer konstanter (longs og doubles) to på hinanden følgende pladser i tabellen, selv om den anden af disse pladser er et fantomindeks, der aldrig bruges direkte.

Typen af hvert element (konstant) i konstantpuljen identificeres af et indledende byte-tag. Antallet af bytes efter dette tag og deres fortolkning er derefter afhængig af tag-værdien. De gyldige konstante typer og deres tag-værdier er:

Tag byte Supplerende bytes Beskrivelse af konstant Version indført
1 2+x bytes
(variabel)
UTF-8 (Unicode)-streng: en tegnstreng med et 16-bit tal (type u2), der angiver antallet af bytes i den kodede streng, der følger umiddelbart efter (hvilket kan være forskelligt fra antallet af tegn). Bemærk, at den anvendte kodning faktisk ikke er UTF-8, men indebærer en mindre ændring af Unicode-standardkodningsformen. 1.0.2
3 4 bytes Tal: et signeret 32-bit to’s komplement-tal i big-endian-format 1.0.2
4 4 bytes 4 bytes Float: et 32-bit enkeltpræcisions IEEE 754-flydepunktstal med enkelt præcision 1.0.2
5 8 bytes Langt: et signeret 64-bit tokomplementært tal i big-endian-format (fylder to pladser i konstantpuljetabellen) 1.0.2
6 8 bytes Double: et 64-bit dobbeltpræcisions IEEE 754-flydepunktstal med dobbelt præcision (tager to pladser i den konstante pooltabel) 1.0.2
7 2 bytes Klassereference: et indeks i konstantpuljen til en UTF-8-streng, der indeholder det fuldt kvalificerede navn på klassen (i internt format) (big-endian) 1.0.2
8 2 bytes String-reference: et indeks i konstantpuljen til en UTF-8-streng (også big-endian) 1.0.2
9 4 bytes Feltreference: to indekser inden for konstantpuljen, hvoraf det første peger på en klassereference, det andet på en navne- og typebeskrivelse. (big-endian) 1.0.2
10 4 bytes Metod-reference: to indekser inden for konstantpuljen, hvoraf det første peger på en Klassereference, det andet på en Navne- og Type-deskriptor. (big-endian) 1.0.2
11 4 bytes Interface-metodehenvisning: to indekser i konstantpuljen, hvoraf det første peger på en klassereference, det andet på en navne- og typedeskriptor. (big-endian) 1.0.2
12 4 bytes Navn- og typedeskriptor: to indekser til UTF-8-strenge inden for konstantpuljen, hvoraf det første repræsenterer et navn (identifikator) og det andet en specielt kodet typedeskriptor. 1.0.2
15 3 bytes Metodehåndtag: Denne struktur bruges til at repræsentere et metodehåndtag og består af en byte type deskriptor efterfulgt af et indeks i konstantpuljen. 7
16 2 bytes Metodetype: Denne struktur anvendes til at repræsentere en metodetype og består af et indeks i konstantpuljen. 7
17 4 bytes Dynamisk: Denne bruges til at angive en dynamisk beregnet konstant, der produceres ved påkaldelse af en bootstrap-metode. 11
18 4 bytes InvokeDynamic: Dette bruges af en invokedynamic-instruktion til at angive en bootstrap-metode, navnet på den dynamiske invocation, argument- og returtyperne for opkaldet og eventuelt en sekvens af yderligere konstanter kaldet statiske argumenter til bootstrap-metoden. 7
19 2 bytes Modul: Dette bruges til at identificere et modul. 9
20 2 bytes Pakke: Dette bruges til at identificere en pakke, der eksporteres eller åbnes af et modul. 9

Der findes kun to integrale konstante typer, nemlig heltal og long. Andre integrale typer, der forekommer i højniveausproget, f.eks. boolean, byte og short, skal repræsenteres som en integerkonstant.

Klassenavne i Java, når de er fuldt kvalificerede, er traditionelt punktsepareret, f.eks. “java.lang.Object”. Men i klassereferencekonstanterne på lavt niveau vises en intern form, som i stedet bruger skråstreger, f.eks. “java/lang/Object”.

Unicode-strenge er trods tilnavnet “UTF-8-streng” faktisk ikke kodet i henhold til Unicode-standarden, selv om den ligner. Der er to forskelle (se UTF-8 for en fuldstændig diskussion). Den første er, at kodepunktet U+0000 er kodet som to-byte-sekvensen C0 80 (i hex) i stedet for standardkodningen på én byte 00. Den anden forskel er, at supplerende tegn (tegn uden for BMP ved U+10000 og derover) indkodes ved hjælp af en surrogatpar-konstruktion svarende til UTF-16 i stedet for at blive direkte indkodet ved hjælp af UTF-8. I dette tilfælde er hver af de to surrogater kodet separat i UTF-8. F.eks. er U+1D11E kodet som 6-byte-sekvensen ED A0 B4 ED B4 9E i stedet for den korrekte 4-byte UTF-8-kodning af F0 9D 84 9E.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.