Fichier de classe Java

SectionsEdit

Il y a 10 sections de base à la structure du fichier de classe Java:

  • Numéro magique : 0xCAFEBABE
  • Version du format du fichier de classe : les versions mineures et majeures du fichier de classe
  • Pool de constantes : Pool de constantes pour la classe
  • Drapeaux d’accès : par exemple si la classe est abstraite, statique, etc.
  • Cette classe : Le nom de la classe actuelle
  • Super classe : Le nom de la super classe
  • Interfaces : Toute interface dans la classe
  • Champs : Tous les champs de la classe
  • Méthodes : Toutes les méthodes de la classe
  • Attributs : Tout attribut de la classe (par exemple le nom du fichier source, etc.)

Magic NumberEdit

Les fichiers de classe sont identifiés par l’en-tête de 4 octets suivant (en hexadécimal) : CA FE BA BE (les 4 premières entrées du tableau ci-dessous). L’histoire de ce nombre magique a été expliquée par James Gosling en faisant référence à un restaurant de Palo Alto:

« Nous avions l’habitude d’aller déjeuner dans un endroit appelé St Michael’s Alley. Selon la légende locale, dans un passé très sombre, le Grateful Dead s’y produisait avant de devenir célèbre. C’était un endroit assez funky qui était définitivement un Grateful Dead Kinda Place. Quand Jerry est mort, ils ont même érigé un petit sanctuaire bouddhiste. Quand on y allait, on appelait l’endroit le « Café Dead ». Quelque part, on a remarqué que c’était un nombre HEX. J’étais en train de réorganiser un code de format de fichier et j’avais besoin de quelques nombres magiques : un pour le fichier d’objets persistants et un pour les classes. J’ai utilisé CAFEDEAD pour le format de fichier objet, et en cherchant des mots hexadécimaux de 4 caractères après « CAFE » (cela semblait être un bon thème), je suis tombé sur BABE et j’ai décidé de l’utiliser. À ce moment-là, cela ne semblait pas très important ou destiné à aller ailleurs que dans la poubelle de l’histoire. CAFEBABE est donc devenu le format de fichier de classe, et CAFEDEAD le format d’objet persistant. Mais la facilité d’objet persistant a disparu, et avec elle l’utilisation de CAFEDEAD – il a finalement été remplacé par RMI.

General layoutEdit

Parce que le fichier de classe contient des éléments de taille variable et ne contient pas également des décalages de fichiers intégrés (ou pointeurs), il est généralement analysé séquentiellement, du premier octet vers la fin. Au niveau le plus bas, le format du fichier est décrit en termes de quelques types de données fondamentales :

  • u1 : un entier de 8 bits non signé
  • u2 : un entier de 16 bits non signé dans l’ordre des octets big-endian
  • u4 : un entier de 32 bits non signé dans l’ordre des octets big-endian
  • tableau : un tableau d’éléments de longueur variable d’un certain type. Le nombre d’éléments dans le tableau est identifié par un nombre de comptage précédent (le comptage est un u2), mais la taille en octets du tableau ne peut être déterminée qu’en examinant chacun de ses éléments.

Certains de ces types fondamentaux sont ensuite réinterprétés comme des valeurs de plus haut niveau (comme des chaînes de caractères ou des nombres à virgule flottante), selon le contexte.Il n’y a pas d’application de l’alignement des mots, et donc aucun octet de remplissage n’est jamais utilisé.La disposition globale du fichier de classe est indiquée dans le tableau suivant.

Octet de décalage taille type ou valeur description
0 4 octets u1 =
0xCA hex
numéro magique (CAFEBABE) utilisé pour identifier le fichier comme conforme au format de fichier de classe
1 u1 =
0xFE hex
2 u1 =
0xBA hex
3 u1 =
0xBE hex
4 2 octets u2 numéro de la version mineure du format de fichier de classe utilisé
5
6 2 octets u2 numéro de version majeure du format de fichier de classe utilisé.

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).
Pour des détails sur les numéros de version antérieurs, voir la note de bas de page 1 de The JavaTM Virtual Machine Specification 2nd edition

7
8 2 bytes u2 constant pool count, nombre d’entrées dans le tableau constant pool suivant. Ce compte est au moins un plus grand que le nombre réel d’entrées ; voir la discussion suivante.
9
10 cpsize (variable) table table de pool constant, un tableau d’entrées de pool constant de taille variable, contenant des éléments tels que des nombres littéraux, des chaînes de caractères et des références à des classes ou des méthodes. Indexé à partir de 1, contenant (nombre de pools de constantes – 1) nombre d’entrées au total (voir note).
….
10+cpsize 2 bytes u2 flags d’accès, un bitmask
11+cpsize
12+cpsize 2 bytes u2 identifie cette classe, index dans le pool de constantes vers une entrée de type « Class »
13+cpsize
14+cpsize 2 bytes u2 identifie la super classe, index dans le pool de constantes à une entrée de type « Class »
15+cpsize
16+cpsize 2 bytes u2 compte d’interfaces, nombre d’entrées dans la table d’interface suivante
17+cpsize
18+cpsize isize (variable) table table d’interface : un tableau de longueur variable d’index de pool constant décrivant les interfaces implémentées par cette classe
18+cpsize+isize 2 octets u2 nombre de champs, nombre d’entrées dans la table de champs suivante
19+cpsize+isize
20+cpsize+isize fsize (variable) table table de champs, tableau de longueur variable de champs

chaque élément est une structure field_info définie dans https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.5

20+cpsize+isize+fsize 2 bytes u2 method count, nombre d’entrées dans le tableau de méthodes suivant
21+cpsize+isize+fsize
22+cpsize+isize+fsize msize (variable) table table de méthodes, tableau de méthodes de longueur variable

chaque élément est une structure method_info définie dans https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.6

22+cpsize+isize+fsize+msize 2 octets u2 nombre d’attributs, nombre d’entrées dans le tableau d’attributs suivant
23+cpsize+isize+fsize+msize
24+cpsize+isize+fsize+msize asize (variable) table tableau d’attributs, tableau d’attributs de longueur variable

chaque élément est une structure attribute_info définie dans https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7

Représentation dans un langage de programmation de type CEdit

Comme le C ne supporte pas les tableaux à longueur variable multiple dans une struct, le code ci-dessous ne compilera pas et ne sert que de démonstration.

struct Class_File_Format { u4 magic_number; u2 minor_version; u2 major_version; u2 constant_pool_count; cp_info constant_pool; u2 access_flags; u2 this_class; u2 super_class; u2 interfaces_count; u2 interfaces; u2 fields_count; field_info fields; u2 methods_count; method_info methods; u2 attributes_count; attribute_info attributes;}

Le tableau de constantesEdit

Le tableau de constantes est l’endroit où la plupart des valeurs constantes littérales sont stockées. Cela inclut des valeurs telles que des nombres de toutes sortes, des chaînes de caractères, des noms d’identifiants, des références à des classes et des méthodes, et des descripteurs de type. Tous les index, ou références, à des constantes spécifiques dans la table du pool de constantes sont donnés par des nombres de 16 bits (type u2), où la valeur d’index 1 fait référence à la première constante de la table (la valeur d’index 0 est invalide).

En raison de choix historiques faits pendant le développement du format de fichier, le nombre de constantes dans la table du pool de constantes n’est pas réellement le même que le compte du pool de constantes qui précède la table. Tout d’abord, la table est indexée à partir de 1 (plutôt que 0), mais le compte doit en fait être interprété comme l’indice maximum plus un. De plus, deux types de constantes (longues et doubles) occupent deux emplacements consécutifs dans la table, bien que le second emplacement de ce type soit un index fantôme qui n’est jamais directement utilisé.

Le type de chaque élément (constante) dans le pool de constantes est identifié par une étiquette initiale d’octets. Le nombre d’octets suivant cette balise et leur interprétation dépendent ensuite de la valeur de la balise. Les types de constantes valides et leurs valeurs de balise sont :

Octet de marquage Octets supplémentaires Description de la constante Version introduite
1 2+x octets
(variable)
Chaîne de caractères UTF-8 (Unicode) : une chaîne de caractères préfixée par un nombre de 16 bits (type u2) indiquant le nombre d’octets dans la chaîne codée qui suit immédiatement (qui peut être différent du nombre de caractères). Notez que l’encodage utilisé n’est pas réellement UTF-8, mais implique une légère modification de la forme d’encodage standard Unicode. 1.0.2
3 4 octets Integer : un nombre signé de 32 bits en complément à deux au format big-endian 1.0.2
4 4 octets Float : un nombre à virgule flottante IEEE 754 de 32 bits à simple précision 1.0.2
5 8 octets Long : un nombre signé à complément à deux de 64 bits au format big-endian (prend deux emplacements dans la table de pool de constantes) 1,0.2
6 8 octets Double : un nombre à virgule flottante IEEE 754 à double précision de 64 bits (prend deux emplacements dans la table de pool de constantes) 1,0.2
7 2 octets Référence de classe : un index dans le pool de constantes vers une chaîne UTF-8 contenant le nom de classe entièrement qualifié (au format interne) (big-endian) 1.0.2
8 2 octets Référence à la chaîne : un index dans le pool de constantes à une chaîne UTF-8 (big-endian aussi) 1.0.2
9 4 octets Référence de champ : deux index au sein du pool de constantes, le premier pointant vers une référence de classe, le second vers un descripteur de nom et de type. (big-endian) 1.0.2
10 4 octets Référence à la méthode : deux index au sein du pool de constantes, le premier pointant sur une référence de classe, le second sur un descripteur de nom et de type. (big-endian) 1.0.2
11 4 octets Référence à une méthode d’interface : deux index au sein du pool de constantes, le premier pointant vers une référence de Classe, le second vers un descripteur de Nom et de Type. (big-endian) 1.0.2
12 4 octets Descripteur de nom et de type : deux index vers des chaînes UTF-8 au sein du pool de constantes, le premier représentant un nom (identifiant) et le second un descripteur de type spécialement codé. 1.0.2
15 3 octets Poignée de méthode : cette structure est utilisée pour représenter une poignée de méthode et consiste en un octet de descripteur de type, suivi d’un index au sein du pool de constantes. 7
16 2 octets Type de méthode : cette structure est utilisée pour représenter un type de méthode, et consiste en un index dans le pool de constantes. 7
17 4 octets Dynamique : elle est utilisée pour spécifier une constante calculée dynamiquement produite par l’invocation d’une méthode d’amorçage. 11
18 4 octets InvokeDynamic : elle est utilisée par une instruction invokedynamic pour spécifier une méthode bootstrap, le nom d’invocation dynamique, les types d’argument et de retour de l’appel, et éventuellement, une séquence de constantes supplémentaires appelées arguments statiques de la méthode bootstrap. 7
19 2 octets Module : il est utilisé pour identifier un module. 9
20 2 octets Paquet : ceci est utilisé pour identifier un paquet exporté ou ouvert par un module. 9

Il n’existe que deux types constants intégraux, integer et long. Les autres types intégraux apparaissant dans le langage de haut niveau, tels que boolean, byte et short doivent être représentés comme une constante integer.

Les noms de classe en Java, lorsqu’ils sont entièrement qualifiés, sont traditionnellement séparés par des points, tels que « java.lang.Object ». Cependant, au sein des constantes de référence de classe de bas niveau, une forme interne apparaît qui utilise des barres obliques à la place, comme « java/lang/Object ».

Les chaînes Unicode, malgré le surnom de « chaîne UTF-8 », ne sont pas réellement codées selon la norme Unicode, bien qu’elle soit similaire. Il existe deux différences (voir UTF-8 pour une discussion complète). La première est que le point de code U+0000 est encodé sous la forme de la séquence de deux octets C0 80 (en hexadécimal) au lieu de l’encodage standard d’un seul octet 00. La deuxième différence est que les caractères supplémentaires (ceux qui sont en dehors du BMP à U+10000 et au-dessus) sont codés en utilisant une construction de paires de substituts similaire à UTF-16 plutôt que d’être directement codés en utilisant UTF-8. Dans ce cas, chacun des deux substituts est codé séparément en UTF-8. Par exemple, U+1D11E est codé comme la séquence de 6 octets ED A0 B4 ED B4 9E, plutôt que le codage correct de 4 octets en UTF-8 de F0 9D 84 9E.

.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.