Top Qs
Tijdlijn
Chat
Perspectief
Classfile
gecompileerd Java-bestand Van Wikipedia, de vrije encyclopedie
Remove ads
Een classfile bevat bytecode die uitgevoerd kan worden door een Java Virtual Machine. Classfiles kunnen inmiddels worden geproduceerd door diverse compilers (Javac, JRuby, Scala, Groovy, Kotlin, Clojure, Jython, Fantom, Gosu, en andere), wanneer deze de broncode compileert.
Een classfile bestaat uit de volgende onderdelen:
Header
De header bevat een magic number en versieinformatie. Een magic number is een constante aan het begin van een file die aangeeft dat de file een bepaald soort data bevat. Dit geldt niet alleen voor classfiles, maar ook voor veel andere bestandsformaten, bijvoorbeeld .GIF files en .ZIP files. Het magic number waarmee iedere classfile begint is 0xCAFEBABE
.
Het magic number wordt gevolgd door 4 bytes die de versie van de gebruikte specificatie aangeven: eerst 2 bytes voor de minor version, dan 2 bytes voor de major version. Een header voor een classfile met versie 49.0 (J2SE 5.0) ziet er dan als volgt uit:
cafebabe00000031
Remove ads
Constantpool
De header wordt gevolgd door de constantpool. In de constantpool wordt een aantal constanten gedefinieerd die in de rest van de classfile gebruikt worden. De eerste 2 bytes duiden het aantal constanten in de constantpool aan.
Iedere waarde in de pool wordt voorafgegaan door een tag (1 byte) die het datatype aangeeft (en dus ook het aantal bytes dat de daaropvolgende waarde inneemt). Er zijn 11 tags, onder andere voor (UTF-8) strings, integers en verwijzingen naar methoden en fields.
Het begin van een constantpool kan er als volgt uitzien:
0003 De pool bevat 3 constanten. 01 De eerste constante is een string. 0005 De string is 5 bytes. 48656c6c6f "Hello".
In dit geval bevat de pool 3 constanten (alleen de eerste wordt hier weergegeven). De eerste constante is een UTF-8 string (aangegeven door tag 1[1]). In het geval van een string wordt de tag gevolgd door 2 bytes die de lengte van de string aangeven, in dit geval 5 bytes. Hierna volgt de string zelf: "hello", gecodeerd in hexidecimaal als 48656c6c6f
.
Remove ads
Klasse-informatie
Na de constantpool volgt er informatie over de klasse die door deze bytecodefile gedefinieerd wordt, zoals de naam en de superclass. Dit gedeelte bestaat uit 8 bytes, verdeeld in 4 items van elk 2 bytes:
- De access flags van de klasse, zoals "public", "abstract" of "final". Deze worden gecodeerd als een bitmask[2].
- De naam van de klasse. Dit is een verwijzing naar een item in de constantpool dat een string met de naam van de klasse bevat.
- De superklasse. Dit is weer een verwijzing naar een string in de constantpool.
- Het aantal interfaces dat deze klasse implementeert.
Als de klasse één of meer interfaces implementeert volgt vervolgens een lijst met de geïmplementeerde interfaces.
Fields en methods
Samenvatten
Perspectief
Deze sectie beschrijft de velden (fields, of attributen) en methoden van de klasse. De sectie begint met 2 bytes. Deze specificeren het aantal velden van de klasse. Vervolgens volgt de lijst met velden. Daarna komen er weer 2 bytes, die het aantal methoden van deze klasse aangeven. Deze worden op hun beurt weer gevolgd door de methoden.
Velden en methoden worden op dezelfde manier gecodeerd. Elk gedeelte dat een veld of een methode specificeert begint met 2 bytes die de access flags (zoals "static", "public", "abstract", enzovoort) aangeven, gecodeerd als bitmask[3]. De volgende 2 bytes bevatten de naam van de methode of het veld. Dit is weer een verwijzing naar een string in de constantpool.
Type descriptor
Hierna volgen nog 2 bytes die het type van de methode of het veld specificeren (de zogenaamde type descriptor). Het type van een veld geeft aan welk type waarden het veld kan bevatten. Het type van een methode geeft aan hoeveel argumenten de methode verwacht, van welke datatype deze argumenten zijn en welk datatype de methode retourneert.
Deze uit 2 bytes bestaande type descriptor is weer een verwijzing naar een string in de constantpool. Bijvoorbeeld: de string in de constantpool waarnaar de type-descriptor van de main-routine wijst is altijd ([Ljava/lang/String;)V
. Dit geeft aan dat de main-routine een array (aangegeven door [
) van strings (aangegeven door Ljava/lang/String
) als argument verwacht en void (aangegeven door V
) als returntype heeft.
Attributen
Na de type-descriptor volgen eventuele attributen van de methode of het veld. Een veld kan bijvoorbeeld een ConstValue
-attribuut hebben dat de beginwaarde van het veld specificeert. Meestal hebben velden echter geen attributen.
De sectie met attributen begint met 2 bytes die het aantal attributen voor deze methode of dit veld aangeven. Een attribuut wordt als volgt gecodeerd: eerst 2 bytes die weer naar een string in de constantpool verwijzen. Deze string bevat de naam van het attribuut. Vervolgens 4 bytes die de lengte van de data die bij het attribuut hoort aangeven.
De classfile specificatie maakt het mogelijk om zelf nieuwe attributen toe te voegen. De JVM die de classfile uitvoert negeert attributen die hij niet ondersteunt.
Het code-attribuut
Methoden hebben in meestal in ieder geval één attribuut: een Code
-attribuut. Hierin wordt onder andere gespecificeert hoeveel items op de stack de methode (maximaal) gebruikt, en hoeveel lokale variabelen. Ook wordt in het Code-attribuut de implementatie van de methode (de body) opgenomen.
Na de body van de methode volgt nog informatie over de exceptions die de methode afhandeld[4]. En ten slotte kan het Code-attribuut op zijn beurt ook nog weer attributen hebben. Die worden dan na de informatie over exceptions gespecificeerd.
Voorbeeld van een Code-attribuut
Het Code-attribuut van een methode kan er als volgt uitzien:
0003 De naam van dit attribuut is de derde string in de constantpool (in dit geval "Code"). 00000009 De data van dit attribuut is 9 bytes groot. 0002 Deze methode gebruikt 2 items op de stack. 0000 Deze methode gebruikt geen lokale variabelen. 00000001 De lengte van de code zelf (de implementatie van de methode) is 1 byte. b1 De body van de methode bestaat hier uit slechts 1 instructie, met opcode 5.
De bovenstaande methode bevat slechts één instructie: een return-statement (deze heeft opcode 5).
Remove ads
Class attributen
De classfile eindigt met (nog) een lijst attributen. Deze gelden voor de hele class en worden op dezelfde manier gecodeerd als de attributen van velden en methodes. Ook hier geeft de specificatie de mogelijkheid om nieuwe attributen te implementeren. De specificatie zelf definieerd alleen het SourceFile
-attribuut, die de naam van de file met broncode bevat waarvan de classfile afkomstig is (voor debuggers).
Remove ads
Opcodes en instructies
Wikiwand - on
Seamless Wikipedia browsing. On steroids.
Remove ads