File di classe Java - Java class file
| Tipo di media Internet | application/java-vm, application/x-httpd-java |
|---|---|
| Sviluppato da | Microsistemi solari |
Un file di classe Java è un file (con l' estensione del nome file .class ) contenente il bytecode Java che può essere eseguito sulla Java Virtual Machine (JVM) . Un file di classe Java viene solitamente prodotto da un compilatore Java da file sorgente del linguaggio di programmazione Java ( file .java ) contenenti classi Java (in alternativa, è possibile utilizzare anche altri linguaggi JVM per creare file di classe). Se un file sorgente ha più di una classe, ogni classe viene compilata in un file di classe separato.
Le JVM sono disponibili per molte piattaforme e un file di classe compilato su una piattaforma verrà eseguito su una JVM di un'altra piattaforma. Ciò rende le applicazioni Java indipendenti dalla piattaforma .
Storia
L'11 dicembre 2006, il formato del file di classe è stato modificato in Java Specification Request (JSR) 202.
Layout e struttura del file
Sezioni
Ci sono 10 sezioni di base per la struttura del file di classe Java:
- Numero magico : 0xCAFEBABE
- Versione del formato file di classe : le versioni minore e principale del file di classe
- Constant Pool : Pool di costanti per la classe
- Flag di accesso : ad esempio se la classe è astratta, statica, ecc.
- Questa classe : il nome della classe corrente
- Super classe : il nome della super classe
- Interfacce : tutte le interfacce della classe
- Campi : tutti i campi della classe
- Metodi : tutti i metodi della classe
- Attributi : qualsiasi attributo della classe (ad esempio il nome del file sorgente, ecc.)
Numero magico
I file di classe sono identificati dalla seguente intestazione di 4 byte (in esadecimale ): (le prime 4 voci nella tabella seguente). La storia di questo numero magico è stata spiegata da James Gosling riferendosi ad un ristorante di Palo Alto :
CA FE BA BE
"Andavamo a pranzo in un posto chiamato St Michael's Alley. Secondo la leggenda locale, nel profondo oscuro passato, i Grateful Dead si esibivano lì prima che diventassero grandi. Era un posto piuttosto funky che era sicuramente un Grateful Dead Kinda Place. Quando Jerry è morto, hanno persino messo su un piccolo santuario in stile buddista. Quando andavamo lì, ci riferivamo al posto come Cafe Dead. Da qualche parte lungo la linea si è notato che questo era un numero esadecimale. I stava rinnovando il codice del formato file e aveva bisogno di un paio di numeri magici : uno per il file oggetto persistente e uno per le classi.Ho usato CAFEDEAD per il formato del file oggetto e in grepping per le parole esadecimali di 4 caratteri che si adattano dopo "CAFE " (sembrava essere un buon tema) mi sono imbattuto in BABE e ho deciso di usarlo. A quel tempo, non sembrava molto importante o destinato ad andare da nessuna parte tranne che nel cestino della storia. Quindi CAFEBABE è diventato il file di classe format e CAFEDEAD era il formato oggetto persistente, ma la funzione oggetto persistente andò a rotoli sì, e con esso è andato l'uso di CAFEDEAD - alla fine è stato sostituito da RMI .
Layout generale
Poiché il file di classe contiene elementi di dimensioni variabili e non contiene anche offset di file incorporati (o puntatori), viene in genere analizzato in sequenza, 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 nell'ordine dei byte big-endian
- u4 : un intero senza segno a 32 bit nell'ordine dei byte big-endian
- table : 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 è u2), ma la dimensione in byte della tabella può essere determinata solo esaminando ciascuno dei suoi elementi.
Alcuni di questi tipi fondamentali vengono quindi reinterpretati come valori di livello superiore (come stringhe o numeri in virgola mobile), a seconda del contesto. Non c'è l'imposizione dell'allineamento delle parole, quindi non vengono mai utilizzati byte di riempimento. Il layout generale del file di classe è come mostrato nella tabella seguente.
| byte offset | dimensione | tipo o valore | descrizione |
|---|---|---|---|
| 0 | 4 byte | u1 = 0xCA esadecimale |
numero magico (CAFEBABE) utilizzato per identificare il file come conforme al formato del file di classe |
| 1 | u1 = 0xFE esadecimale |
||
| 2 | u1 = 0xBA esadecimale |
||
| 3 | u1 = 0xBE esadecimale |
||
| 4 | 2 byte | u2 | numero di versione minore del formato di file di classe utilizzato |
| 5 | |||
| 6 | 2 byte | u2 | numero di versione principale del formato di file di classe utilizzato. Java SE 17 = 61 (0x3D esadecimale), |
| 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 seguente discussione. |
| 9 | |||
| 10 | cpssize (variabile) | tavolo | tabella del pool costante, un array di voci del pool costante di dimensioni variabili, contenente elementi come numeri letterali, stringhe e riferimenti a classi o metodi. Indicizzato a partire da 1, contenente ( conteggio pool costante - 1) numero di voci in totale (vedi nota). |
| ... | |||
| ... | |||
| ... | |||
| 10+ cpssize | 2 byte | u2 | flag di accesso, una maschera di bit |
| 11+ cps | |||
| 12+ cps | 2 byte | u2 | identifica questa classe, indicizza nel pool costante a una voce di tipo "Classe" |
| 13+ cps | |||
| 14+ cps | 2 byte | u2 | identifica la super classe, indicizza nel pool costante a una voce di tipo "Classe" |
| 15+ cps | |||
| 16+ cps | 2 byte | u2 | conteggio interfaccia, numero di voci nella seguente tabella interfaccia |
| 17+ cps | |||
| 18+ cps | dimensione (variabile) | tavolo | tabella delle interfacce: un array a lunghezza variabile di indici di pool costanti che descrivono le interfacce implementate da questa classe |
| ... | |||
| ... | |||
| ... | |||
| 18+ cpssize + isize | 2 byte | u2 | conteggio dei campi, numero di voci nella seguente tabella dei campi |
| 19+ cpssize + isize | |||
| 20+ cpssize + isize | fsize (variabile) | tavolo | tabella dei campi, array di campi a 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+ cpssize + isize + fsize | 2 byte | u2 | conteggio del metodo, numero di voci nella seguente tabella dei metodi |
| 21+ cpssize + isize + fsize | |||
| 22+ cpssize + isize + fsize | msize (variabile) | tavolo | tabella dei metodi, array di metodi a 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+ cpssize + isize + fsize + msize | 2 byte | u2 | conteggio degli attributi, numero di voci nella seguente tabella degli attributi |
| 23+ cpssize + isize + fsize + msize | |||
| 24+ cpssize + isize + fsize + msize | dimensione (variabile) | tavolo | tabella degli attributi, array di attributi a 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 C
Poiché C non supporta più array di lunghezza variabile all'interno di una struttura, il codice seguente non verrà compilato e funge solo da dimostrazione.
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];
}
La piscina costante
Il tavolo da biliardo costante è il punto in cui viene archiviata la maggior parte dei valori costanti letterali. Ciò 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 costanti specifiche nella tabella del pool di 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 delle scelte storiche effettuate durante lo sviluppo del formato file, il numero di costanti nella tabella del pool costante non è in realtà lo stesso del conteggio del pool costante che precede la tabella. Innanzitutto, la tabella viene indicizzata a partire da 1 (anziché da 0), ma il conteggio deve essere effettivamente interpretato come l'indice massimo più uno. Inoltre, due tipi di costanti (long e double) occupano due slot consecutivi nella tabella, sebbene il secondo di tali slot sia un indice fantasma che non viene mai utilizzato direttamente.
Il tipo di ogni elemento (costante) nel pool di costanti è identificato da un tag byte iniziale . Il numero di byte che seguono questo tag e la loro interpretazione dipendono quindi dal valore del tag. I tipi di costanti validi e i loro valori di tag sono:
| Tagga byte | Byte aggiuntivi | Descrizione della costante | Versione introdotta |
|---|---|---|---|
| 1 | 2+ x byte (variabile) |
Stringa UTF-8 (Unicode): una stringa di caratteri preceduta da un numero a 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 utilizzata non è effettivamente UTF-8 , ma comporta una leggera modifica del modulo di codifica standard Unicode. | 1.0.2 |
| 3 | 4 byte | Intero: un numero in complemento a due a 32 bit con segno in formato big-endian | 1.0.2 |
| 4 | 4 byte | Float: un numero a virgola mobile IEEE 754 a precisione singola a 32 bit | 1.0.2 |
| 5 | 8 byte | Long: un numero in complemento a due a 64 bit con segno in formato big-endian (occupa due slot nel tavolo da biliardo costante) | 1.0.2 |
| 6 | 8 byte | Double: un numero a virgola mobile IEEE 754 a doppia precisione a 64 bit (occupa due slot nel tavolo da biliardo costante) | 1.0.2 |
| 7 | 2 byte | Riferimento classe: un indice all'interno del pool di costanti a una stringa UTF-8 contenente il nome completo della classe (in formato interno ) (big-endian) | 1.0.2 |
| 8 | 2 byte | Riferimento stringa: un indice all'interno del pool costante a una stringa UTF-8 (anche big-endian) | 1.0.2 |
| 9 | 4 byte | Riferimento campo: due indici all'interno del pool di costanti, il primo che punta a un riferimento Class, il secondo a un descrittore Name e Type. (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 Class, il secondo a un descrittore Name e Type. (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 Class, il secondo a un descrittore Name e Type. (big endian) | 1.0.2 |
| 12 | 4 byte | Nome e descrittore di tipo: due indici di stringhe UTF-8 all'interno del pool di costanti, il primo che rappresenta un nome (identificatore) e il secondo un descrittore di tipo appositamente codificato. | 1.0.2 |
| 15 | 3 byte | Handle del metodo: questa struttura viene utilizzata per rappresentare un handle del metodo e consiste in un byte del descrittore di tipo, seguito da un indice all'interno del pool di costanti. | 7 |
| 16 | 2 byte | Tipo di metodo: questa struttura viene utilizzata per rappresentare un tipo di metodo e consiste in un indice all'interno del pool di costanti. | 7 |
| 17 | 4 byte | Dinamico: viene utilizzato per specificare una costante calcolata dinamicamente prodotta dall'invocazione di un metodo bootstrap. | 11 |
| 18 | 4 byte | InvokeDynamic: viene utilizzato da un'istruzione invokedynamic per specificare un metodo bootstrap, il nome dell'invocazione dinamica, l'argomento e i tipi restituiti della chiamata e, facoltativamente, una sequenza di costanti aggiuntive chiamate argomenti statici per il metodo bootstrap. | 7 |
| 19 | 2 byte | Modulo: serve per identificare un modulo. | 9 |
| 20 | 2 byte | Pacchetto: viene utilizzato per identificare un pacchetto esportato o aperto da un modulo. | 9 |
Esistono solo due tipi di costanti integrali, intero e lungo. Altri tipi integrali che compaiono 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 Class di basso livello, viene visualizzato un modulo interno che utilizza invece le barre, come "java/lang/Object".
Le stringhe Unicode, nonostante il moniker "stringa UTF-8", non sono effettivamente codificate secondo lo standard Unicode, sebbene sia simile. Ci sono due differenze (vedi UTF-8 per una discussione completa). Il primo è che il punto di codice U+0000 è codificato come sequenza a due byte C0 80(in esadecimale) invece della codifica standard a byte singolo 00. La seconda differenza è che i caratteri supplementari (quelli al di fuori del BMP a U+10000 e oltre) sono codificati utilizzando una costruzione a coppia surrogata simile a UTF-16 anziché essere codificati direttamente utilizzando UTF-8. In questo caso ciascuno dei due surrogati è codificato separatamente in UTF-8. Ad esempio, U+1D11E è codificato come sequenza a 6 byte ED A0 B4 ED B4 9E, anziché come codifica UTF-8 a 4 byte corretta di F0 9D 84 9E.
Guarda anche
Riferimenti
Ulteriori letture
- Tim Lindholm , Frank Yellin (1999). La specifica Java Virtual Machine (seconda ed.). Prentice Hall. ISBN 0-201-43294-3. Estratto il 13-10-2008 .Il documento ufficiale di definizione della Java Virtual Machine , che include il formato del file di classe. Sia la prima che la seconda edizione del libro sono disponibili gratuitamente online per la visualizzazione e/o il download .