Plik klasy Java - Java class file

Plik klasy Java
Rodzaj mediów internetowych aplikacja/java-vm, aplikacja/x-httpd-java
Opracowany przez Mikrosystemy słoneczne

Plik klasy Java to plik (z rozszerzeniem nazwy pliku .class ) zawierający kod bajtowy Java, który można wykonać w wirtualnej maszynie Java (JVM) . Plik klasy Java jest zwykle tworzony przez kompilator Java z plików źródłowych języka programowania Java ( plików .java ) zawierających klasy Java (alternatywnie do tworzenia plików klas można również użyć innych języków JVM ). Jeśli plik źródłowy ma więcej niż jedną klasę, każda klasa jest kompilowana w oddzielny plik klasy.

Maszyny JVM są dostępne dla wielu platform , a plik klasy skompilowany na jednej platformie będzie wykonywany na maszynie JVM innej platformy. Dzięki temu aplikacje Java są niezależne od platformy .

Historia

W dniu 11 grudnia 2006 r. format pliku klasy został zmodyfikowany w ramach żądania specyfikacji Java (JSR) 202.

Układ i struktura plików

Sekcje

Struktura plików klas Java składa się z 10 podstawowych sekcji:

  • Magiczna liczba : 0xCAFEBABE
  • Wersja formatu pliku klasy : podrzędna i główna wersja pliku klasy
  • Stała pula : pula stałych dla klasy
  • Access Flags : na przykład, czy klasa jest abstrakcyjna, statyczna itp.
  • Ta klasa : nazwa obecnej klasy
  • Super klasa : nazwa super klasy
  • Interfejsy : dowolne interfejsy w klasie
  • Pola : dowolne pola w klasie
  • Metody : dowolne metody w klasie
  • Atrybuty : dowolne atrybuty klasy (na przykład nazwa pliku źródłowego itp.)

Magiczny numer

Pliki klas są identyfikowane przez następujący 4- bajtowy nagłówek (w systemie szesnastkowym ): CA FE BA BE(pierwsze 4 wpisy w tabeli poniżej). Historię tej magicznej liczby wyjaśnił James Gosling odnosząc się do restauracji w Palo Alto :

„Kiedyś chodziliśmy na lunch do miejsca o nazwie St Michael's Alley. Według lokalnej legendy, w głębokiej, mrocznej przeszłości występowali tam The Grateful Dead, zanim się rozwinęli. Dead Kinda Place. Kiedy zmarł Jerry , zbudowano nawet małą buddyjską świątynię. Kiedy tam chodziliśmy, nazywaliśmy to miejsce „Cafe Dead”. Gdzieś po drodze zauważono, że to numer HEX. Ja przerabiałem jakiś kod formatu pliku i potrzebowałem kilku magicznych liczb : jednej dla trwałego pliku obiektowego i jednej dla klas.Użyłem CAFEDEAD dla formatu pliku obiektowego i podczas grepowania dla 4-znakowych słów szesnastkowych, które pasują po „CAFE (wydawało się, że to dobry motyw) Uderzyłem BABE i postanowiłem go użyć. W tamtym czasie nie wydawało się to szczególnie ważne ani przeznaczone do nigdzie poza śmietnikiem historii. Tak więc CAFEBABE stało się aktami klasowymi format, a CAFEDEAD był formatem obiektu trwałego, ale funkcja obiektu trwałego przestała działać a wraz z nim poszło użycie CAFEDEAD - ostatecznie został on zastąpiony przez RMI .

Ogólny układ

Ponieważ plik klasy zawiera elementy o zmiennej wielkości i nie zawiera również osadzonych przesunięć plików (lub wskaźników), jest zwykle analizowany sekwencyjnie, od pierwszego bajtu do końca. Na najniższym poziomie format pliku opisany jest za pomocą kilku podstawowych typów danych:

  • u1 : 8-bitowa liczba całkowita bez znaku
  • u2 : 16-bitowa liczba całkowita bez znaku w kolejności bajtów big-endian
  • u4 : 32-bitowa liczba całkowita bez znaku w kolejności bajtów big-endian
  • table : tablica elementów o zmiennej długości pewnego typu. Liczba elementów w tabeli jest identyfikowana przez poprzedzający numer licznika (liczba to u2), ale rozmiar w bajtach tabeli można określić tylko poprzez zbadanie każdego z jej elementów.

Niektóre z tych podstawowych typów są następnie ponownie interpretowane jako wartości wyższego poziomu (takie jak ciągi lub liczby zmiennoprzecinkowe), w zależności od kontekstu. Nie ma wymuszania wyrównania słów, więc nigdy nie używa się bajtów dopełniających. Ogólny układ pliku klasy jest przedstawiony w poniższej tabeli.

przesunięcie bajtów rozmiar typ lub wartość opis
0 4 bajty u1 =
0xCA szesnastkowy
magiczny numer (CAFEBABE) używany do identyfikacji pliku jako zgodnego z formatem pliku klasy
1 u1 =
0xFE szesnastkowy
2 u1 =
0xBA szesnastkowy
3 u1 =
0xBE hex
4 2 bajty u2 podrzędny numer wersji używanego formatu pliku klasy
5
6 2 bajty u2 główny numer wersji używanego formatu pliku klasy.

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 (0 x 34 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 szesnastkowy),
JDK 1,1 = 45 (0x2D szesnastkowy).
Szczegółowe informacje na temat wcześniejszych numerów wersji można znaleźć w przypisie 1 w The JavaTM Virtual Machine Specification 2nd edition

7
8 2 bajty u2 liczba stałych puli, liczba wpisów w następującej tabeli puli stałej. Ta liczba jest co najmniej o jeden większa niż rzeczywista liczba wpisów; patrz następująca dyskusja.
9
10 rozmiar cp (zmienny) Tabela tabela puli stałych, tablica wpisów puli stałych o zmiennej wielkości, zawierająca takie elementy, jak liczby dosłowne, łańcuchy i odwołania do klas lub metod. Indeksowane począwszy od 1, zawierające ( stała liczba puli - 1) łączna liczba wpisów (patrz uwaga).
...
...
...
10+ rozmiar cps 2 bajty u2 flagi dostępu, maska ​​bitowa
11+ rozmiar cps
12+ rozmiar cps 2 bajty u2 identyfikuje klasę, indeksuje do puli stałej do wpisu typu „Klasa”
13+ rozmiar cps
14+ rozmiar cps 2 bajty u2 identyfikuje superklasę , indeks do puli stałej do wpisu typu „Klasa”
15+ rozmiar cps
16+ rozmiar cps 2 bajty u2 liczba interfejsów, liczba wpisów w poniższej tabeli interfejsów
17+ rozmiar cps
18+ rozmiar cps irozmiar (zmienny) Tabela tablica interfejsów: tablica o zmiennej długości stałych indeksów puli opisująca interfejsy zaimplementowane przez tę klasę
...
...
...
18+ rozmiar cp + isize 2 bajty u2 liczba pól, liczba wpisów w poniższej tabeli pól
19+ rozmiar cp + isize
20+ rozmiar cp + isize frozmiar (zmienna) Tabela tabela pól, tablica pól o zmiennej długości

każdy element jest strukturą field_info zdefiniowaną w https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.5

...
...
...
20+ rozmiar cp + isize + fsize 2 bajty u2 liczba metod, liczba wpisów w poniższej tabeli metod
21+ rozmiar cp + isize + fsize
22+ rozmiar cp + isize + fsize mrozmiar (zmienny) Tabela tabela metod, tablica metod o zmiennej długości

każdy element jest strukturą method_info zdefiniowaną w https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.6

...
...
...
22+ cpsize + isize + fsize + msize 2 bajty u2 liczba atrybutów, liczba wpisów w poniższej tabeli atrybutów
23+ rozmiar cp + isize + frozmiar + mrozmiar
24+ cpsize + isize + fsize + msize rozmiar (zmienny) Tabela tablica atrybutów, tablica atrybutów o zmiennej długości

każdy element jest strukturą attribute_info zdefiniowaną w https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7

...
...
...

Reprezentacja w języku programowania podobnym do C

Ponieważ C nie obsługuje wielu tablic o zmiennej długości w strukturze, poniższy kod nie zostanie skompilowany i służy tylko jako demonstracja.

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];
}

Stała pula

Tabela puli stałych to miejsce, w którym przechowywana jest większość wartości stałych dosłownych. Obejmuje to wartości, takie jak liczby wszelkiego rodzaju, łańcuchy, nazwy identyfikatorów, odwołania do klas i metod oraz deskryptory typów. Wszystkie indeksy lub odwołania do określonych stałych w tabeli puli stałych są podane przez liczby 16-bitowe (typ u2), gdzie wartość indeksu 1 odnosi się do pierwszej stałej w tabeli (wartość indeksu 0 jest nieprawidłowa).

Z powodu historycznych wyborów dokonanych podczas opracowywania formatu pliku, liczba stałych w tabeli puli stałej nie jest w rzeczywistości taka sama jak liczba stałych puli poprzedzających tabelę. Po pierwsze, tabela jest indeksowana od 1 (a nie od 0), ale w rzeczywistości liczba powinna być interpretowana jako maksymalny indeks plus jeden. Dodatkowo dwa rodzaje stałych (longs i doubles) zajmują dwa kolejne miejsca w tabeli, chociaż drugi taki slot jest indeksem fantomowym, który nigdy nie jest bezpośrednio używany.

Typ każdej pozycji (stałej) w puli stałej jest identyfikowany przez początkowy znacznik bajtu . Liczba bajtów następujących po tym znaczniku i ich interpretacja zależą od wartości znacznika. Prawidłowe typy stałych i ich wartości znaczników to:

Bajt tagu Dodatkowe bajty Opis stałej Wprowadzona wersja
1 2+ x bajtów
(zmienna)
Ciąg znaków UTF-8 (Unicode): ciąg znaków poprzedzony 16-bitową liczbą (typ u2) wskazującą liczbę bajtów w zakodowanym ciągu, który następuje bezpośrednio (która może być inna niż liczba znaków). Należy zauważyć, że użyte kodowanie nie jest w rzeczywistości UTF-8 , ale obejmuje niewielką modyfikację standardowego formatu kodowania Unicode. 1.0.2
3 4 bajty Liczba całkowita: podpisana 32-bitowa liczba uzupełniająca do dwójki w formacie big-endian 1.0.2
4 4 bajty Float: 32-bitowa liczba zmiennoprzecinkowa IEEE 754 o pojedynczej precyzji 1.0.2
5 8 bajtów Long: podpisana 64-bitowa liczba uzupełnień do dwójek w formacie big-endian (zajmuje dwa miejsca w tabeli stałej puli) 1.0.2
6 8 bajtów Double: 64-bitowa liczba zmiennoprzecinkowa IEEE 754 o podwójnej precyzji (zajmuje dwa miejsca w tabeli puli stałych) 1.0.2
7 2 bajty Odwołanie do klasy: indeks w puli stałej do ciągu znaków UTF-8 zawierającego w pełni kwalifikowaną nazwę klasy (w formacie wewnętrznym ) (big-endian) 1.0.2
8 2 bajty Odwołanie do łańcucha: indeks w puli stałej do łańcucha UTF-8 (również big-endian) 1.0.2
9 4 bajty Odwołanie do pola: dwa indeksy w puli stałej, pierwszy wskazuje na odwołanie do klasy, drugi na deskryptor nazwy i typu. (big-endian) 1.0.2
10 4 bajty Odwołanie do metody: dwa indeksy w puli stałej, pierwszy wskazuje na odwołanie do klasy, drugi na deskryptor nazwy i typu. (big-endian) 1.0.2
11 4 bajty Odniesienie do metody interfejsu: dwa indeksy w puli stałych, pierwszy wskazuje na odwołanie do klasy, drugi na deskryptor nazwy i typu. (big-endian) 1.0.2
12 4 bajty Deskryptor nazwy i typu: dwa indeksy do ciągów znaków UTF-8 w puli stałej, pierwszy reprezentujący nazwę (identyfikator), a drugi specjalnie zakodowany deskryptor typu. 1.0.2
15 3 bajty Uchwyt metody: ta struktura jest używana do reprezentowania uchwytu metody i składa się z jednego bajtu deskryptora typu, po którym następuje indeks w puli stałej. 7
16 2 bajty Typ metody: ta struktura służy do reprezentowania typu metody i składa się z indeksu w puli stałej. 7
17 4 bajty Dynamic: jest używany do określenia dynamicznie obliczanej stałej wytwarzanej przez wywołanie metody ładowania początkowego. 11
18 4 bajty InvokeDynamic: jest używany przez instrukcję invokedynamic do określenia metody ładowania początkowego, nazwy dynamicznego wywołania, argumentów i typów zwracanych wywołania oraz opcjonalnie sekwencji dodatkowych stałych zwanych argumentami statycznymi metody ładowania początkowego. 7
19 2 bajty Moduł: służy do identyfikacji modułu. 9
20 2 bajty Pakiet: służy do identyfikacji pakietu eksportowanego lub otwieranego przez moduł. 9

Istnieją tylko dwa typy stałych całkowitych, całkowite i długie. Inne typy całkowite występujące w języku wysokiego poziomu, takie jak boolean, byte i short, muszą być reprezentowane jako stała całkowita.

Nazwy klas w Javie, jeśli są w pełni kwalifikowane, są tradycyjnie rozdzielane kropkami, na przykład „java.lang.Object”. Jednak w obrębie stałych referencyjnych klasy niskiego poziomu pojawia się formularz wewnętrzny, który zamiast tego używa ukośników, na przykład „java/język/obiekt”.

Ciągi znaków Unicode, pomimo pseudonimu „ciąg UTF-8”, nie są w rzeczywistości zakodowane zgodnie ze standardem Unicode, chociaż jest podobny. Istnieją dwie różnice ( pełną dyskusję można znaleźć w UTF-8 ). Po pierwsze, punkt kodowy U+0000 jest zakodowany jako sekwencja dwubajtowa C0 80(w szesnastce) zamiast standardowego kodowania jednobajtowego 00. Druga różnica polega na tym, że znaki uzupełniające (te poza BMP na poziomie U+10000 i wyższym) są kodowane przy użyciu konstrukcji pary zastępczej podobnej do UTF-16, a nie bezpośrednio przy użyciu UTF-8. W tym przypadku każdy z dwóch surogatów jest zakodowany oddzielnie w UTF-8. Na przykład U+1D11E jest zakodowany jako 6-bajtowa sekwencja ED A0 B4 ED B4 9Ezamiast poprawnego 4-bajtowego kodowania UTF-8 w F0 9D 84 9E.

Zobacz też

Bibliografia

Dalsza lektura

  • Tim Lindholm , Frank Yellin (1999). Specyfikacja wirtualnej maszyny Java (wyd. drugie). Sala Prezydencka. Numer ISBN 0-201-43294-3. Źródło 2008-10-13 .Oficjalny dokument definiujący wirtualną maszynę Java , który zawiera format pliku klasy. Zarówno pierwsze, jak i drugie wydanie książki są bezpłatnie dostępne online do przeglądania i/lub pobierania .