Java-Klassendatei - Java class file
Internet-Medientyp | application/java-vm, application/x-httpd-java |
---|---|
Entwickelt von | Sonne Mikrosysteme |
Eine Java-Klassendatei ist eine Datei (mit der Dateinamenerweiterung .class ), die Java-Bytecode enthält , der auf der Java Virtual Machine (JVM) ausgeführt werden kann . Eine Java-Klassendatei wird normalerweise von einem Java-Compiler aus Quelldateien der Java-Programmiersprache ( .java- Dateien) erzeugt, die Java- Klassen enthalten (alternativ können auch andere JVM-Sprachen zum Erstellen von Klassendateien verwendet werden). Wenn eine Quelldatei mehr als eine Klasse hat, wird jede Klasse in eine separate Klassendatei kompiliert.
JVMs sind für viele Plattformen verfügbar , und eine auf einer Plattform kompilierte Klassendatei wird auf einer JVM einer anderen Plattform ausgeführt. Dies macht Java-Anwendungen plattformunabhängig .
Geschichte
Am 11. Dezember 2006 wurde das Klassendateiformat gemäß Java Specification Request (JSR) 202 geändert .
Dateilayout und -struktur
Abschnitte
Es gibt 10 grundlegende Abschnitte zur Dateistruktur der Java-Klasse:
- Magische Zahl : 0xCAFEBABE
- Version des Klassendateiformats: die Neben- und Hauptversionen der Klassendatei
- Constant Pool : Pool von Konstanten für die Klasse
- Access Flags : zum Beispiel ob die Klasse abstrakt, statisch usw. ist.
- Diese Klasse : Der Name der aktuellen Klasse
- Superklasse : Der Name der Superklasse
- Schnittstellen : Alle Schnittstellen in der Klasse
- Felder : Alle Felder in der Klasse
- Methoden : Alle Methoden in der Klasse
- Attribute : Alle Attribute der Klasse (zum Beispiel der Name der Quelldatei usw.)
Magische Zahl
Klassendateien werden durch den folgenden 4- Byte- Header (in hexadezimal ) identifiziert : CA FE BA BE
(die ersten 4 Einträge in der Tabelle unten). Die Geschichte dieser magischen Zahl wurde von James Gosling anhand eines Restaurants in Palo Alto erklärt :
„Wir gingen zum Mittagessen an einem Ort namens St. Michael's Alley. Einer lokalen Legende zufolge traten die Grateful Dead dort in der tiefen dunklen Vergangenheit auf, bevor sie groß herauskamen. Es war ein ziemlich funky Ort, der definitiv ein Grateful war Dead Kinda Place. Als Jerry starb, errichteten sie sogar einen kleinen buddhistischen Schrein. Als wir dorthin gingen, bezeichneten wir den Ort als Cafe Dead. Irgendwann fiel auf, dass dies eine HEX-Nummer war habe einen Dateiformatcode neu gestaltet und benötigte ein paar magische Zahlen : eine für die persistente Objektdatei und eine für Klassen. Ich habe CAFEDEAD für das Objektdateiformat verwendet und beim Grepping nach 4- stelligen Hex-Wörtern, die nach "CAFE" passen " (es schien ein gutes Thema zu sein) Ich stieß auf BABE und beschloss, es zu verwenden. Zu dieser Zeit schien es nicht besonders wichtig oder dazu bestimmt, irgendwohin zu gehen, außer in den Mülleimer der Geschichte. Also wurde CAFEBABE zur Klassendatei Format und CAFEDEAD war das Format für persistente Objekte ja, und damit auch die Verwendung von CAFEDEAD - es wurde schließlich durch RMI ersetzt .
Hauptgestaltung
Da die Klassendatei Elemente variabler Größe und keine eingebetteten Dateioffsets (oder Zeiger) enthält, wird sie normalerweise sequenziell vom ersten Byte bis zum Ende geparst. Auf der untersten Ebene wird das Dateiformat anhand einiger grundlegender Datentypen beschrieben:
- u1 : eine vorzeichenlose 8-Bit- Ganzzahl
- u2 : eine vorzeichenlose 16-Bit- Ganzzahl in Big-Endian- Byte-Reihenfolge
- u4 : eine 32-Bit- Ganzzahl ohne Vorzeichen in Big-Endian-Byte-Reihenfolge
- table : ein Array von Elementen mit variabler Länge eines Typs. Die Anzahl der Elemente in der Tabelle wird durch eine vorangehende Zählnummer identifiziert (der Zählwert ist ein u2), aber die Größe der Tabelle in Bytes kann nur durch Untersuchen jedes ihrer Elemente bestimmt werden.
Einige dieser grundlegenden Typen werden dann je nach Kontext als Werte höherer Ebene (wie Strings oder Gleitkommazahlen) neu interpretiert. Es gibt keine Erzwingung der Wortausrichtung, und daher werden niemals Füllbytes verwendet. Das Gesamtlayout der Klassendatei ist in der folgenden Tabelle dargestellt.
Byte-Offset | Größe | Typ oder Wert | Bezeichnung |
---|---|---|---|
0 | 4 Bytes | u1 = 0xCA hex |
magische Zahl (CAFEBABE), die verwendet wird, um die Datei als dem Klassendateiformat entsprechend zu identifizieren |
1 | u1 = 0xFE hex |
||
2 | u1 = 0xBA hex |
||
3 | u1 = 0xBE hex |
||
4 | 2 Byte | u2 | Nebenversionsnummer des verwendeten Klassendateiformats |
5 | |||
6 | 2 Byte | u2 | Hauptversionsnummer des verwendeten Klassendateiformats. Java SE 17 = 61 (0x3D hex), |
7 | |||
8 | 2 Byte | u2 | konstanter Poolzähler, Anzahl der Einträge in der folgenden konstanten Pooltabelle. Diese Anzahl ist mindestens um eins größer als die tatsächliche Anzahl der Einträge; siehe folgende Diskussion. |
9 | |||
10 | cpsize (variabel) | Tisch | Konstanten-Pool-Tabelle, ein Array von Konstanten-Pool-Einträgen variabler Größe, die Elemente wie Literalzahlen, Zeichenfolgen und Verweise auf Klassen oder Methoden enthalten. Indiziert beginnend bei 1, enthält ( konstante Poolanzahl - 1) Anzahl der Einträge insgesamt (siehe Hinweis). |
... | |||
... | |||
... | |||
10+ cp-Größe | 2 Byte | u2 | Zugriffsflags, eine Bitmaske |
11+ Cp-Größe | |||
12+ cp-Größe | 2 Byte | u2 | identifiziert diese Klasse, Index in den Konstantenpool zu einem Eintrag vom Typ "Klasse" |
13+ cp-Größe | |||
14+ cp-Größe | 2 Byte | u2 | identifiziert Superklasse , Index in den Konstantenpool zu einem Eintrag vom Typ "Klasse" |
15+ cp-Größe | |||
16+ Cp-Größe | 2 Byte | u2 | Schnittstellenanzahl, Anzahl der Einträge in der folgenden Schnittstellentabelle |
17+ Cp-Größe | |||
18+ Cp-Größe | Größe (variabel) | Tisch | Schnittstellentabelle: ein Array mit konstanten Pool-Indizes variabler Länge, das die von dieser Klasse implementierten Schnittstellen beschreibt |
... | |||
... | |||
... | |||
18+ Cpsize + Isize | 2 Byte | u2 | Feldanzahl, Anzahl der Einträge in der folgenden Feldtabelle |
19+ Cpsize + Isize | |||
20+ Cpsize + Isize | fsize (variabel) | Tisch | Feldtabelle, Array von Feldern mit variabler Länge
Jedes Element ist eine field_info-Struktur, die in https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.5 definiert ist |
... | |||
... | |||
... | |||
20+ cpsize + isize + fsize | 2 Byte | u2 | Methodenanzahl, Anzahl der Einträge in der folgenden Methodentabelle |
21+ cpsize + isize + fsize | |||
22+ cpsize + isize + fsize | mgröße (variabel) | Tisch | Methodentabelle, Array mit Methoden variabler Länge
Jedes Element ist eine method_info-Struktur, die in https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.6 . definiert ist |
... | |||
... | |||
... | |||
22+ cpsize + isize + fsize + msize | 2 Byte | u2 | Attributanzahl, Anzahl der Einträge in der folgenden Attributtabelle |
23+ cpsize + isize + fsize + msize | |||
24+ cpsize + isize + fsize + msize | Größe (variabel) | Tisch | Attributtabelle, Array von Attributen variabler Länge
Jedes Element ist eine attribute_info-Struktur, die in https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7 definiert ist |
... | |||
... | |||
... |
Darstellung in einer C-ähnlichen Programmiersprache
Da C nicht mehrere Arrays mit variabler Länge innerhalb einer Struktur unterstützt, wird der folgende Code nicht kompiliert und dient nur als Demonstration.
struct Class_File_Format {
u4 magic_number;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count - 1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
Der ständige Pool
In der Konstanten-Pool-Tabelle werden die meisten Literalkonstantenwerte gespeichert. Dazu gehören Werte wie Zahlen aller Art, Zeichenfolgen, Bezeichnernamen, Verweise auf Klassen und Methoden sowie Typdeskriptoren. Alle Indizes oder Verweise auf bestimmte Konstanten in der Konstanten-Pool-Tabelle werden durch 16-Bit-Zahlen (Typ u2) angegeben, wobei sich der Indexwert 1 auf die erste Konstante in der Tabelle bezieht (Indexwert 0 ist ungültig).
Aufgrund historischer Entscheidungen, die während der Dateiformatentwicklung getroffen wurden, entspricht die Anzahl der Konstanten in der Konstanten-Pool-Tabelle nicht der Konstanten-Pool-Zählung, die der Tabelle vorangeht. Zuerst wird die Tabelle beginnend bei 1 (statt 0) indiziert, aber die Anzahl sollte eigentlich als maximaler Index plus eins interpretiert werden. Außerdem belegen zwei Konstantentypen (Longs und Doubles) zwei aufeinanderfolgende Slots in der Tabelle, obwohl der zweite Slot ein Phantomindex ist, der nie direkt verwendet wird.
Der Typ jedes Elements (Konstante) im Konstantenpool wird durch ein anfängliches Byte- Tag identifiziert . Die Anzahl der diesem Tag folgenden Bytes und deren Interpretation sind dann vom Tag-Wert abhängig. Die gültigen Konstantentypen und ihre Tag-Werte sind:
Tag-Byte | Zusätzliche Bytes | Beschreibung der Konstanten | Version eingeführt |
---|---|---|---|
1 | 2+ x Byte (variabel) |
UTF-8 (Unicode)-String: eine Zeichenfolge, der eine 16-Bit-Zahl (Typ u2) vorangestellt ist, die die Anzahl der Bytes in der unmittelbar folgenden codierten Zeichenfolge angibt (die von der Anzahl der Zeichen abweichen kann). Beachten Sie, dass die verwendete Codierung nicht wirklich UTF-8 ist , sondern eine geringfügige Modifikation der Unicode-Standardcodierungsform beinhaltet. | 1.0.2 |
3 | 4 Bytes | Integer: eine vorzeichenbehaftete 32-Bit -Zweierkomplement- Zahl im Big-Endian-Format | 1.0.2 |
4 | 4 Bytes | Float: eine 32-Bit- IEEE 754- Gleitkommazahl mit einfacher Genauigkeit | 1.0.2 |
5 | 8 Byte | Long: eine vorzeichenbehaftete 64-Bit-Zweierkomplement-Zahl im Big-Endian-Format (braucht zwei Slots in der konstanten Pooltabelle) | 1.0.2 |
6 | 8 Byte | Double: eine 64-Bit-Gleitkommazahl mit doppelter Genauigkeit nach IEEE 754 (braucht zwei Slots in der konstanten Pooltabelle) | 1.0.2 |
7 | 2 Byte | Klassenreferenz: ein Index innerhalb des Konstantenpools auf einen UTF-8-String, der den vollqualifizierten Klassennamen (im internen Format ) enthält (Big-Endian) | 1.0.2 |
8 | 2 Byte | String-Referenz: ein Index innerhalb des Konstanten-Pools auf einen UTF-8-String (auch Big-Endian) | 1.0.2 |
9 | 4 Bytes | Feldreferenz: zwei Indizes innerhalb des Konstantenpools, der erste zeigt auf eine Klassenreferenz, der zweite auf einen Name- und Typ-Deskriptor. (Big-Endian) | 1.0.2 |
10 | 4 Bytes | Methodenreferenz: zwei Indizes innerhalb des Konstantenpools, der erste zeigt auf eine Klassenreferenz, der zweite auf einen Name- und Typ-Deskriptor. (Big-Endian) | 1.0.2 |
11 | 4 Bytes | Schnittstellenmethodenreferenz: zwei Indizes innerhalb des Konstantenpools, der erste zeigt auf eine Klassenreferenz, der zweite auf einen Name- und Typ-Deskriptor. (Big-Endian) | 1.0.2 |
12 | 4 Bytes | Name und Typdeskriptor: zwei Indizes zu UTF-8-Strings innerhalb des Konstantenpools, wobei der erste einen Namen (Bezeichner) darstellt und der zweite einen speziell codierten Typdeskriptor. | 1.0.2 |
fünfzehn | 3 Byte | Methodenhandle: Diese Struktur wird verwendet, um eine Methodenhandle darzustellen und besteht aus einem Byte des Typdeskriptors, gefolgt von einem Index innerhalb des Konstantenpools. | 7 |
16 | 2 Byte | Methodentyp: Diese Struktur wird verwendet, um einen Methodentyp darzustellen und besteht aus einem Index innerhalb des Konstantenpools. | 7 |
17 | 4 Bytes | Dynamisch: Dies wird verwendet, um eine dynamisch berechnete Konstante anzugeben, die durch den Aufruf einer Bootstrap-Methode erzeugt wird. | 11 |
18 | 4 Bytes | InvokeDynamic: Dies wird von einer invokedynamic- Anweisung verwendet, um eine Bootstrap-Methode, den dynamischen Aufrufnamen , die Argument- und Rückgabetypen des Aufrufs und optional eine Folge zusätzlicher Konstanten, die als statische Argumente bezeichnet werden, für die Bootstrap-Methode anzugeben. | 7 |
19 | 2 Byte | Modul: Dies wird verwendet, um ein Modul zu identifizieren. | 9 |
20 | 2 Byte | Paket: Dies wird verwendet, um ein Paket zu identifizieren, das von einem Modul exportiert oder geöffnet wurde. | 9 |
Es gibt nur zwei ganzzahlige Konstantentypen, integer und long. Andere ganzzahlige Typen, die in der Hochsprache vorkommen, wie boolean, byte und short, müssen als ganzzahlige Konstante dargestellt werden.
Klassennamen in Java werden, wenn sie vollständig qualifiziert sind, traditionell durch Punkte getrennt, wie z. B. "java.lang.Object". Innerhalb der Klassenreferenzkonstanten auf niedriger Ebene wird jedoch ein internes Formular angezeigt, das stattdessen Schrägstriche verwendet, z. B. "java/lang/Object".
Die Unicode-Strings sind trotz des Monikers "UTF-8-String" nicht wirklich nach dem Unicode-Standard codiert, obwohl er ähnlich ist. Es gibt zwei Unterschiede (siehe UTF-8 für eine vollständige Diskussion). Der erste besteht darin, dass der Codepunkt U+0000 als Zwei-Byte-Sequenz C0 80
(in Hex) anstelle der Standard-Einzelbyte-Kodierung kodiert wird 00
. Der zweite Unterschied besteht darin, dass zusätzliche Zeichen (die außerhalb des BMP bei U+10000 und höher) mit einer Surrogat-Paar-Konstruktion ähnlich UTF-16 kodiert werden, anstatt direkt mit UTF-8 kodiert zu werden. In diesem Fall wird jedes der beiden Surrogate separat in UTF-8 kodiert. Beispielsweise wird U+1D11E als 6-Byte-Sequenz codiert ED A0 B4 ED B4 9E
und nicht als korrekte 4-Byte-UTF-8-Codierung von F0 9D 84 9E
.
Siehe auch
Verweise
Weiterlesen
- Tim Lindholm , Frank Yellin (1999). Die Java Virtual Machine Specification (Zweite Aufl.). Lehrlingssaal. ISBN 0-201-43294-3. Abgerufen 2008-10-13 .Das offizielle Definitionsdokument der Java Virtual Machine , das das Klassendateiformat enthält. Sowohl die erste als auch die zweite Ausgabe des Buches stehen online zur Ansicht und/oder zum Download kostenlos zur Verfügung .