Java-Klassendatei - Java class file

Java-Klassendatei
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),
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).
Einzelheiten zu früheren Versionsnummern finden Sie in Fußnote 1 in The JavaTM Virtual Machine Specification 2nd edition

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 9Eund 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 .