Programmering

Java-klassen fil livsstil

Velkommen til en annen del av "Under panseret." I forrige måneds artikkel diskuterte jeg Java Virtual Machine, eller JVM, den abstrakte datamaskinen som alle Java-programmer er samlet for. Hvis du ikke er kjent med JVM, kan det være lurt å lese forrige måneds artikkel før denne. I denne artikkelen gir jeg et innblikk i den grunnleggende strukturen og livsstilen til Java-klassefilen.

Født til å reise

Java-klassefilen er et nøyaktig definert format for kompilert Java. Java kildekode er samlet i klassefiler som kan lastes inn og utføres av hvilken som helst JVM. Klassefilene kan reise over et nettverk før de lastes inn av JVM.

Faktisk, hvis du leser denne artikkelen via en Java-kompatibel nettleser, flyr klassefiler for simuleringsappleten på slutten av artikkelen over Internett til datamaskinen din akkurat nå. Hvis du vil høre på dem (og datamaskinen din har lydfunksjon), trykker du på følgende knapp:

Du trenger en Java-aktivert nettleser for å se denne appleten

Høres ut som de har det gøy, ikke sant? Det er i deres natur. Java-klassefiler ble designet for å reise bra. De er plattformuavhengige, så de vil være velkomne flere steder. De inneholder bytekoder, det kompakte instruksjonssett for JVM, slik at de kan reise lett. Java-klassefiler zipper kontinuerlig gjennom nettverk i en enorm hastighet for å komme til JVM-er over hele verden.

Hva er i en klassefil?

Java-klassefilen inneholder alt en JVM trenger å vite om en Java-klasse eller et grensesnitt. I rekkefølgen av utseendet i klassefilen er hovedkomponentene: magi, versjon, konstant basseng, tilgangsflagg, denne klassen, superklasse, grensesnitt, felt, metoder og attributter.

Informasjon som er lagret i klassefilen varierer ofte i lengde - det vil si at den faktiske lengden på informasjonen ikke kan forutsies før klassefilen lastes inn. For eksempel kan antall metoder som er oppført i metodekomponenten variere mellom klassefiler, fordi det avhenger av antall metoder som er definert i kildekoden. Slik informasjon er organisert i klassefilen ved å plassere den faktiske informasjonen etter størrelse eller lengde. Når klassen lastes inn av JVM, leses størrelsen på informasjonen med variabel lengde først. Når JVM vet størrelsen, kan den lese riktig informasjon.

Informasjon skrives vanligvis til klassefilen uten mellomrom eller polstring mellom påfølgende informasjon. alt er justert etter bytegrenser. Dette hjelper med å holde klassefiler petite, slik at de blir aerodynamiske når de flyr over nettverk.

Rekkefølgen på komponentene til klassefilen er strengt definert slik at JVM-er kan vite hva de kan forvente og hvor de kan forvente seg når de laster inn en klassefil. For eksempel vet hver JVM at de første åtte bytene i en klassefil inneholder magiske og versjonsnumre, at det konstante bassenget starter på den niende byten, og at tilgangsflaggene følger det konstante bassenget. Men fordi det konstante bassenget er variabelt, vet det ikke nøyaktig hvor tilgangsflaggene befinner seg før det er ferdig med å lese i det konstante bassenget. Når den er ferdig med å lese i det konstante bassenget, vet den at de to neste byte vil være tilgangsflaggene.

Magiske og versjonsnumre

De første fire byte i hver klassefil er alltid 0xCAFEBABE. Dette magiske tallet gjør Java-klassefiler lettere å identifisere, fordi oddsen er liten for at ikke-klassefiler vil starte med samme innledende fire byte. Nummeret kalles magi fordi det kan trekkes opp av en hatt av filformatdesignerne. Det eneste kravet er at det ikke allerede brukes av et annet filformat som kan oppstå i den virkelige verden. Ifølge Patrick Naughton, et sentralt medlem av det opprinnelige Java-teamet, ble det magiske nummeret valgt "lenge før navnet Java noen gang ble uttalt med henvisning til dette språket. Vi lette etter noe morsomt, unikt og lett å huske. Det er bare en tilfeldighet at OxCAFEBABE, en skrå referanse til de søte baristene på Peet's Coffee, var en forhåndsvisning av navnet Java. "

De andre fire byte i klassefilen inneholder hoved- og mindre versjonsnummer. Disse tallene identifiserer versjonen av klassefilformatet som en bestemt klassefil holder seg til, og lar JVMer kontrollere at klassefilen er lastbar. Hver JVM har en maksimal versjon den kan laste, og JVM-er vil avvise klassefiler med senere versjoner.

Konstant basseng

Klassefilen lagrer konstanter tilknyttet klassen eller grensesnittet i det konstante bassenget. Noen konstanter som kan ses i bassenget er bokstavelige strenger, endelige variabelverdier, klassenavn, grensesnittnavn, variabelnavn og -typer, og metodenavn og signaturer. En metode signatur er returtypen og settet med argumenttyper.

Det konstante bassenget er organisert som en rekke elementer med variabel lengde. Hver konstant opptar ett element i matrisen. Gjennom klassefilen refereres det til konstanter med heltallindeksen som indikerer deres posisjon i matrisen. Den opprinnelige konstanten har en indeks på en, den andre konstanten har en indeks på to osv. Den konstante bassenggruppen er innledet med dens arraystørrelse, slik at JVM-er vil vite hvor mange konstanter de kan forvente når de laster inn klassefilen.

Hvert element i det konstante bassenget starter med en en-byte-tag som spesifiserer typen konstant ved den posisjonen i matrisen. Når en JVM tar tak og tolker denne koden, vet den hva som følger koden. For eksempel, hvis en tag indikerer at konstanten er en streng, forventer JVM at de to neste byte skal være strenglengden. Etter denne to-byte lengden, forventer JVM å finne lengde antall byte, som utgjør tegnene i strengen.

I resten av artikkelen vil jeg noen ganger referere til det nte elementet i den konstante bassengmatrisen som constant_pool [n]. Dette gir mening i den grad det konstante bassenget er organisert som en matrise, men husk at disse elementene har forskjellige størrelser og typer, og at det første elementet har en indeks på en.

Få tilgang til flagg

De to første byte etter den konstante poolen, tilgangsflaggene, indikerer om denne filen definerer en klasse eller et grensesnitt, om klassen eller grensesnittet er offentlig eller abstrakt, og (hvis det er en klasse og ikke et grensesnitt) om klassen er endelig.

Denne klassen

De to neste byte, denne klassen komponent, er en indeks i det konstante bassenget. Konstanten det refereres til av denne klassen, constant_pool [denne_klassen], har to deler, en byte-tag og en to-byte navnindeks. Taggen vil være lik CONSTANT_Class, en verdi som indikerer at dette elementet inneholder informasjon om en klasse eller et grensesnitt. Constant_pool [name_index] er en strengkonstant som inneholder navnet på klassen eller grensesnittet.

De denne klassen komponent gir et glimt av hvordan det konstante bassenget brukes. Denne klassen i seg selv er bare en indeks i det konstante bassenget. Når en JVM ser opp constant_pool [denne_klassen], finner den et element som identifiserer seg selv som en CONSTANT_Class med taggen. JVM vet at CONSTANT_Class-elementer alltid har en to-byte-indeks i det konstante bassenget, kalt navnindeks, etter en-byte-koden. Så det ser opp constant_pool [name_index] for å få strengen som inneholder navnet på klassen eller grensesnittet.

Super klasse

Følger denne klassen komponenten er super klasse komponent, en annen to-byte indeks i det konstante bassenget. Constant_pool [superklasse] er et CONSTANT_Class-element som peker på navnet på superklassen som denne klassen stammer fra.

Grensesnitt

Grensesnittkomponenten starter med en to-byte-telling av antall grensesnitt implementert av klassen (eller grensesnittet) som er definert i filen. Rett etter er en matrise som inneholder en indeks i det konstante bassenget for hvert grensesnitt implementert av klassen. Hvert grensesnitt er representert av et CONSTANT_Class-element i det konstante bassenget som peker på navnet på grensesnittet.

Enger

Feltkomponenten starter med en to-byte-telling av antall felt i denne klassen eller grensesnittet. Et felt er en forekomst eller klassevariabel av klassen eller grensesnittet. Etter tellingen følger en rekke strukturer med variabel lengde, en for hvert felt. Hver struktur avslører informasjon om ett felt, for eksempel feltets navn, type, og hvis det er en endelig variabel, dens konstante verdi. Noe informasjon er inneholdt i selve strukturen, og noe er inneholdt i konstante bassengsteder som strukturen peker på.

De eneste feltene som vises i listen er de som ble erklært av klassen eller grensesnittet som er definert i filen; ingen felt arvet fra superklasser eller supergrensesnitt vises i listen.

Metoder

Metodekomponenten starter med en to-byte-telling av antall metoder i klassen eller grensesnittet. Denne tellingen inkluderer bare de metodene som er eksplisitt definert av denne klassen, ikke noen metoder som kan arves fra superklasser. Etter metodetellingen er metodene i seg selv.

Strukturen for hver metode inneholder flere opplysninger om metoden, inkludert metodebeskrivelsen (returtype og argumentliste), antall stabelord som kreves for metodens lokale variabler, det maksimale antall stabelord som kreves for metoden operand stabel, en tabell med unntak fanget av metoden, bytekodesekvensen og en linjenummertabell.

Attributter

Å hente bak er attributtene, som gir generell informasjon om den aktuelle klassen eller grensesnittet definert av filen. Attributtseksjonen har to byte antall antall attributter, etterfulgt av attributtene selv. For eksempel er ett attributt kildekodeattributtet; den avslører navnet på kildefilen som denne klassefilen ble samlet fra. JVM-er vil stille ignorere alle attributter de ikke kjenner igjen.

Blir lastet: en simulering av en klassefil som når JVM-destinasjonen

Appleten nedenfor simulerer en JVM som laster inn en klassefil. Klassefilen som lastes inn i simuleringen ble generert av javac-kompilatoren gitt følgende Java-kildekode:

class Act {public static void doMathForever () {int i = 0; mens (sann) {i + = 1; i * = 2; }}} 

Ovenstående kodebit kommer fra forrige måneds artikkel om JVM. Det er den samme metoden doMathForever () utført av EternalMath-appleten fra forrige måneds artikkel. Jeg valgte denne koden for å gi et reelt eksempel som ikke var for komplisert. Selv om koden kanskje ikke er veldig nyttig i den virkelige verden, kompileres den til en ekte klassefil, som lastes inn av simuleringen nedenfor.

GettingLoaded-appleten lar deg kjøre klassebelastningssimulering ett trinn av gangen. For hvert trinn underveis kan du lese om neste bit byte som er i ferd med å bli fortært og tolket av JVM. Bare trykk på "Step" -knappen for å få JVM til å konsumere neste del. Ved å trykke "Tilbake" vil du angre forrige trinn, og ved å trykke "Tilbakestill" vil simuleringen gå tilbake til sin opprinnelige tilstand, slik at du kan starte på nytt fra begynnelsen.

JVM vises nederst til venstre og forbruker strømmen av byte som utgjør klassefilen Act.class. Byte vises i hex-streaming ut av en server nederst til høyre. Bytene reiser rett mot venstre, mellom serveren og JVM, en del om gangen. Biten som JVM skal forbruke ved neste "Step" -knapptrykk vises i rødt. Disse markerte byte er beskrevet i det store tekstområdet over JVM. Eventuelle gjenværende byte utover neste del vises i svart.

Jeg har prøvd å forklare hver bit byte i tekstområdet. Det er derfor mye detaljer i tekstområdet, og det kan være lurt å skimme gjennom alle trinnene først for å få den generelle ideen, og deretter se tilbake for mer informasjon.

Glad å klikke.

Du trenger en Java-aktivert nettleser for å se denne appleten.

Klikk her for kildekoden til GettingLoaded. For å kjøre denne appleten på egen hånd, trenger du også de to filene som denne appleten henter fra serveren, ASCII-filen som inneholder teksten for hvert trinn, og selve Act.class-filen. Klikk her for kildekoden til lydprogrammet Flying Class Files.

BEMERKNING: De små skriftene: "The Java Class File Lifestyle" Article Copyright (c) 1996 Bill Venners. Alle rettigheter forbeholdt. "GettingLoaded" Applet Copyright (c) 1996 Artima Software Company. Alle rettigheter forbeholdt.

: END_ENDMERK

Bill Venners er president for Artima Software Company. Gjennom Artima gjør han tilpasset programvareutvikling og rådgivning.

Lær mer om dette emnet

  • Java Virtual Machine Specification, det offisielle ordet fra Sun.

    //java.sun.com/1.0alpha3/doc/vmspec/vmspec_1.html

  • Når den kommer ut, boken Java Virtual Machine Specification, //www.aw.com/cp/lindholm-yellin.html, av Tim Lindholm og Frank Yellin (ISBN 0-201-63452-X), en del av Java-serien, //www.aw.com/cp/ javaseries.html), fra Addison-Wesley, vil trolig være den beste JVM-ressursen.
  • Et utkast til kapittel 4 av Java Virtual Machine Specification, som beskriver klassefilformatet og bytekodeverifisereren, kan hentes fra JavaSoft.

    //java.sun.com/java.sun.com/newdocs.html

Denne historien, "The Java class file lifestyle" ble opprinnelig utgitt av JavaWorld.

$config[zx-auto] not found$config[zx-overlay] not found