File di classe Java

SezioniModifica

Ci sono 10 sezioni di base nella struttura del file di classe Java:

  • Magic Number: 0xCAFEBABE
  • Versione del formato del file di classe: le versioni minori e maggiori del file di classe
  • Constant Pool: Pool di costanti per la classe
  • Flags di accesso: per esempio se la classe è astratta, statica, ecc.
  • Questa classe: Il nome della classe corrente
  • Super Classe: Il nome della super classe
  • Interfacce: Qualsiasi interfaccia nella classe
  • Campi: Qualsiasi campo nella classe
  • Metodi: Qualsiasi metodo nella classe
  • Attributi: Qualsiasi attributo della classe (per esempio il nome del file sorgente, ecc.)

Magic NumberEdit

I file della classe sono identificati dalla seguente intestazione di 4 byte (in esadecimale): CA FE BA BE (le prime 4 voci della tabella sottostante). La storia di questo numero magico è stata spiegata da James Gosling riferendosi a un ristorante di Palo Alto:

“Andavamo a pranzo in un posto chiamato St Michael’s Alley. Secondo la leggenda locale, nel profondo e oscuro passato, i Grateful Dead si esibivano lì prima di diventare famosi. Era un posto piuttosto funky che era decisamente un Grateful Dead Kinda Place. Quando Jerry morì, costruirono anche un piccolo santuario buddista. Quando ci andavamo, ci riferivamo al posto come Cafe Dead. Da qualche parte lungo la linea si è notato che questo era un numero HEX. Stavo rinnovando il codice del formato dei file e avevo bisogno di un paio di numeri magici: uno per il file degli oggetti persistenti e uno per le classi. Ho usato CAFEDEAD per il formato del file oggetto, e cercando parole esadecimali di 4 caratteri che andassero bene dopo “CAFE” (sembrava essere un buon tema) mi sono imbattuto in BABE e ho deciso di usarlo; a quel tempo, non sembrava terribilmente importante o destinato ad andare da qualche parte se non nel cestino della storia. Così CAFEBABE divenne il formato dei file di classe, e CAFEDEAD era il formato degli oggetti persistenti. Ma la struttura dell’oggetto persistente se ne andò, e con essa l’uso di CAFEDEAD – alla fine fu sostituito da RMI.

Layout generaleEdit

Perché il file di classe contiene elementi di dimensioni variabili e non contiene anche offset di file incorporati (o puntatori), è tipicamente analizzato in modo sequenziale, dal primo byte verso la fine. Al livello più basso il formato del file è descritto in termini di alcuni tipi di dati fondamentali:

  • u1: un intero senza segno a 8 bit
  • u2: un intero senza segno a 16 bit in ordine byte big-endian
  • u4: un intero senza segno a 32 bit in ordine byte big-endian
  • tabella: un array di elementi di lunghezza variabile di qualche tipo. Il numero di elementi nella tabella è identificato da un numero di conteggio precedente (il conteggio è un u2), ma la dimensione in byte della tabella può essere determinata solo esaminando ciascuno dei suoi elementi.

Alcuni di questi tipi fondamentali sono poi reinterpretati come valori di livello superiore (come stringhe o numeri in virgola mobile), a seconda del contesto.Non c’è applicazione dell’allineamento delle parole, e quindi non vengono mai usati byte di riempimento.Il layout complessivo del file di classe è quello mostrato nella tabella seguente.

byte offset dimensione tipo o valore descrizione
0 4 byte u1 =
0xCA hex
numero magico (CAFEBABE) usato per identificare il file come conforme al formato class file
1 u1 =
0xFE hex
2 u1 =
0xBA hex
3 u1 =
0xBE hex
4 2 byte u2 numero versione minore del formato di file di classe utilizzato
5
6 2 byte u2 numero di versione maggiore del formato di file di classe utilizzato.

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).
Per i dettagli dei numeri di versione precedenti vedere la nota 1 a The JavaTM Virtual Machine Specification 2nd edition

7
8 2 byte u2 conteggio pool costante, numero di voci nella seguente tabella pool costante. Questo conteggio è almeno uno maggiore del numero effettivo di voci; vedere la discussione seguente.
9
10 cpsize (variabile) table constant pool table, un array di voci constant pool di dimensioni variabili, contenenti elementi come numeri letterali, stringhe e riferimenti a classi o metodi. Indicizzata a partire da 1, contenente (conteggio del pool di costanti – 1) numero di voci in totale (vedi nota).
10+cpsize 2 byte u2 flag di accesso, una bitmask
11+cpsize
12+cpsize 2 byte u2 identifica questa classe, indice nel pool di costanti ad una voce di tipo “Classe”
13+cpsize
14+cpsize 2 byte u2 identifica la super classe, indice nel pool costante di una voce di tipo “Classe”
15+cpsize
16+cpsize 2 byte u2 conteggio interfacce, numero di voci nella seguente tabella di interfaccia
17+cpsize
18+cpsize isize (variabile) table interface table: un array di lunghezza variabile di indici di pool costanti che descrivono le interfacce implementate da questa classe
18+cpsize+isize 2 byte u2 conteggio campi, numero di voci nella seguente tabella dei campi
19+cpsize+isize
20+cpsize+isize fsize (variabile) table tabella dei campi, array di campi di lunghezza variabile

ogni elemento è una struttura field_info definita in https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.5

20+cpsize+isize+fsize 2 byte u2 conteggio metodo, numero di voci nella seguente tabella dei metodi
21+cpsize+isize+fsize
22+cpsize+isize+fsize msize (variabile) table method table, array di metodi di lunghezza variabile

ogni elemento è una struttura method_info definita in https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.6

22+cpsize+isize+fsize+msize 2 byte u2 conteggio attributi, numero di voci nella seguente tabella degli attributi
23+cpsize+isize+fsize+msize
24+cpsize+isize+fsize+msize asize (variabile) table tabella degli attributi, array di attributi di lunghezza variabile

ogni elemento è una struttura attribute_info definita in https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7

Rappresentazione in un linguaggio di programmazione simile al CEdit

Siccome il C non supporta array multipli di lunghezza variabile all’interno di una struct, il codice che segue non verrà compilato e serve solo come dimostrazione.

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

Il pool di costantiEdit

La tabella del pool di costanti è dove la maggior parte dei valori costanti letterali sono memorizzati. Questo include valori come numeri di tutti i tipi, stringhe, nomi di identificatori, riferimenti a classi e metodi, e descrittori di tipo. Tutti gli indici, o riferimenti, a specifiche costanti nella tabella delle costanti sono dati da numeri a 16 bit (tipo u2), dove il valore dell’indice 1 si riferisce alla prima costante nella tabella (il valore dell’indice 0 non è valido).

A causa di scelte storiche fatte durante lo sviluppo del formato del file, il numero di costanti nella tabella delle costanti non è effettivamente lo stesso del conteggio delle costanti che precede la tabella. Innanzitutto, la tabella è indicizzata a partire da 1 (invece che da 0), ma il conteggio dovrebbe essere interpretato come l’indice massimo più uno. Inoltre, due tipi di costanti (lunghe e doppie) occupano due slot consecutivi nella tabella, anche se il secondo slot è un indice fantasma che non viene mai usato direttamente.

Il tipo di ogni elemento (costante) nel pool di costanti è identificato da un tag iniziale di byte. Il numero di byte che segue questo tag e la loro interpretazione dipendono poi dal valore del tag. I tipi di costante validi e i loro valori di tag sono:

Tag byte Byte aggiuntivi Descrizione della costante Versione introdotta
1 2+x byte
(variabile)
StringaUTF-8 (Unicode): una stringa di caratteri preceduta da un numero di 16 bit (tipo u2) che indica il numero di byte nella stringa codificata che segue immediatamente (che può essere diverso dal numero di caratteri). Si noti che la codifica usata non è in realtà UTF-8, ma comporta una leggera modifica della forma di codifica standard Unicode. 1.0.2
3 4 byte Integer: un numero a due complementi firmato a 32 bit in formato big-endian 1.0.2
4 4 byte Float: un numero in virgola mobile IEEE 754 a 32 bit a precisione singola 1.0.2
5 8 byte Long: un numero a due complementi firmato a 64 bit in formato big-endian (prende due slot nella tabella delle costanti) 1.0.2
6 8 byte Double: un numero in virgola mobile IEEE 754 a 64 bit a doppia precisione (occupa due slot nella tabella delle costanti) 1.0.2
7 2 byte Riferimento alla classe: un indice all’interno del pool di costanti per una stringa UTF-8 contenente il nome completo della classe (in formato interno) (big-endian) 1.0.2
8 2 byte Riferimento a una stringa UTF-8 (anche big-endian) 1.0.2
9 4 byte Riferimento al campo: due indici all’interno del pool di costanti, il primo che punta a un riferimento alla classe, il secondo a un descrittore di nome e tipo. (big-endian) 1.0.2
10 4 byte Riferimento al metodo: due indici all’interno del pool di costanti, il primo che punta a un riferimento di classe, il secondo a un descrittore di nome e tipo. (big-endian) 1.0.2
11 4 byte Riferimento al metodo dell’interfaccia: due indici all’interno del pool di costanti, il primo che punta a un riferimento alla classe, il secondo a un descrittore di nome e tipo. (big-endian) 1.0.2
12 4 byte Nome e descrittore del tipo: due indici a stringhe UTF-8 all’interno del pool di costanti, il primo rappresentante un nome (identificatore) e il secondo un descrittore del tipo appositamente codificato. 1.0.2
15 3 byte Method handle: questa struttura è usata per rappresentare un method handle e consiste in un byte di type descriptor, seguito da un indice all’interno del constant pool. 7
16 2 byte Tipo di metodo: questa struttura è usata per rappresentare un tipo di metodo e consiste in un indice all’interno del pool di costanti. 7
17 4 byte Dynamic: è usata per specificare una costante calcolata dinamicamente prodotta dall’invocazione di un metodo bootstrap. 11
18 4 byte InvokeDynamic: è usato da un’istruzione invokedynamic per specificare un metodo bootstrap, il nome dell’invocazione dinamica, i tipi di argomento e ritorno della chiamata, e opzionalmente, una sequenza di costanti aggiuntive chiamate argomenti statici al metodo bootstrap. 7
19 2 byte Modulo: è usato per identificare un modulo. 9
20 2 byte Pacchetto: è usato per identificare un pacchetto esportato o aperto da un modulo. 9

Ci sono solo due tipi di costante integrale, integer e long. Altri tipi integrali che appaiono nel linguaggio di alto livello, come boolean, byte e short devono essere rappresentati come una costante intera.

I nomi delle classi in Java, quando sono completamente qualificati, sono tradizionalmente separati da punti, come “java.lang.Object”. Tuttavia, all’interno delle costanti di riferimento alle classi di basso livello, appare una forma interna che utilizza invece le barre, come “java/lang/Object”.

Le stringhe Unicode, nonostante il moniker “UTF-8 string”, non sono effettivamente codificate secondo lo standard Unicode, sebbene sia simile. Ci sono due differenze (vedi UTF-8 per una discussione completa). La prima è che il punto di codice U+0000 è codificato come sequenza di due byte C0 80 (in esadecimale) invece della codifica standard a un byte 00. La seconda differenza è che i caratteri supplementari (quelli fuori dal BMP a U+10000 e oltre) sono codificati usando una costruzione a coppie surrogate simile a UTF-16 piuttosto che essere codificati direttamente usando UTF-8. In questo caso ciascuno dei due surrogati è codificato separatamente in UTF-8. Per esempio, U+1D11E è codificato come la sequenza a 6 byte ED A0 B4 ED B4 9E, piuttosto che la corretta codifica UTF-8 a 4 byte di F0 9D 84 9E.

.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.