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), |
|
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
.