640 likes | 781 Views
L’architettura della Java Virtual Machine. Implementazione di Linguaggi A.A. 2003/2004 di Gualdani Alessandro. Cos’è la JVM (1). È una macchina astratta stack-based, multi-threading, type safety
E N D
L’architettura dellaJava Virtual Machine Implementazione di Linguaggi A.A. 2003/2004 di Gualdani Alessandro
Cos’è la JVM (1) • È una macchina astratta stack-based, multi-threading, type safety • È indipendente dalla piattaforma la JVM e le Java API realizzano una piattaforma (Java Platform o Java runtime system) su cui vengono eseguite le applicazioni Java
Cos’è la JVM (2) A.java A.class Java compiler bytecode B.java B.class C.java C.class • È un interprete del bytecode: • la fase di compilazione “traduce” i sorgenti java in un linguaggio intermedio, il bytecode, memorizzato nei class files
Cos’è la JVM (3) JVM A.class class loader B.class Java API class files C.class bytecode execution engine native method invocations Host operating system • A runtime la JVM esegue il codice contenuto nei class files
Tipologia di dati La JVM opera su due tipi di dati: • Primitive types “contengono” i primitive values, che sono scalari • Reference types “contengono” i reference values, che sono riferimenti ad oggetti (possono essere pensati come puntatori ad oggetti)
Tipi di dato 32 bit 64 bit 8 bit 16 bit 32 bit 64 bit 16 bit
Method area • È condivisa tra tutti i thread • Memorizza le strutture relative alle classi: - type information - constant pool - field information - method information - variabili di classe (static) - riferimento alla classe ClassLoader - riferimento alla classe Class • Quando la JVM carica un tipo (classe), il class loader legge le informazioni relative dal class file e le passa nuovamente alla JVM la quale le memorizza nella method area
Method area – Type information Per ogni tipo caricato, la JVM deve mantenere le seguenti informazioni: • nome qualificato del tipo (per esempio, per Object il tipo qualificato è java.lang.Object) • nome qualificato del tipo della superclasse • se il tipo è una classe o un’interfaccia • modificatori di tipo (es. public, abstract,…) • lista ordinata dei nomi qualificati delle “superinterfacce”
Method area – Constant Pool • È una rappresentazione (per ogni classe/interfaccia) a runtime della constant_pool table nel class file • Contiene riferimenti simbolici ai campi e metodi usati da una classe • Le entries del constant pool sono referenziate tramite indice, come gli elementi di un array
Method area – Field information Per ogni attributo dichiarato in una classe, vengono memorizzate nella method area le seguenti informazioni: • nome dell’attributo • tipo dell’attributo • modificatori dell’attributo (public, private, protected, …)
Method area – Method information Per ogni metodo dichiarato in una classe, vengono memorizzate nella method area le seguenti informazioni: • nome del metodo • valore di ritorno del metodo • numero e tipi (in ordine) dei parametri • modificatori del metodo(public, private, …) Inoltre vengono mantenute ulteriori informazioni, tra cui: • bytecode del metodo • tavola delle eccezioni
Method area – Variabili di classe • Sono condivise tra tutte le istanze di una classe (e possono essere accedute anche in assenza di istanze della classe) • Facendo parte della classe, sono allocate nella method area
Method area – Riferimento alla classe Class • Per ogni tipo che carica, la JVM crea un’istanza della classe Class • Consente l’accesso alle informazioni contenute nella method area • Può essere ottenuto invocando il metodo: - public static Class forName(String className) (della classe Class) - public final Class getClass() (della classe Object) sull’istanza dell’oggetto
Heap ptr to class data ptr to class data instance data instance data • Viene creato all’avvio della JVM • È condiviso tra tutti i thread • In esso vi sono allocate tutte le istanze delle classi e gli array • È gestito dal garbage collector • NOTA: la Sun, nelle specifiche della JVM, non definisce la rappresentazione degli oggetti né il funzionamento del garbage collector; una possibile rappresentazione degli oggetti è la seguente: Class 1 data Object reference 1 Class 2 data Object reference 2 Heap Method area
Java Stack • Ogni thread ha un suo stack privato (creato al momento della creazione del thread) • Memorizza i frame • Operazioni possibili: push e pop di frame
Frame Ogni frame è composto da tre parti: • local variables • operand stack • frame data Le dimensioni delle local variables e dell’operand stack (in termini di parole) sono noti a compile time e inclusi nel class file, mentre la dimensione del frame data è dipendente dall’implementazione. Quando la JVM invoca un metodo, controlla il class file per determinare il numero di parole richieste per le local variables e l’operand stack: quindi crea un nuovo frame e ne fa il push sul Java stack.
Frame – Local variables • Sono usate per passare i parametri nell’invocazione di un metodo • Sono organizzate in un array • Sono riferite mediante un indice compreso tra 0 e n-1 (dove n è la lunghezza dell’array) • I parametri sono memorizzati nello stesso ordine in cui sono dichiarati; l’indice 0 dell’array è usato per passare (ad esclusione dei metodi static) un reference all’oggetto su cui è stato invocato il metodo (this in Java)
Frame – Operand stack • Viene usato dalla JVM per caricare costanti o valori dalle local variables (attraverso le operazioni push e pop) • Le istruzioni della JVM prendono i loro operandi dall’operand stack (la JVM è stack-based)
Esempio Operand Stack (1) 0 100 local variables 1 98 2 operand stack int a=100; int b=98; int c; ……… c=a+b; Supponiamo l’esecuzione del seguente frammento di codice: Dopo l’esecuzione della prima riga di codice, il frame si presenta così: L’istruzione c=a+b; viene convertita nelle seguenti istruzioni: iload_0 // push l’intero contenuto in local variable 0 iload_1 // push l’intero contenuto in local variable 1 iadd // pop due interi, li somma, push del risultato istore_2// pop di un intero e store in local variable 2
Esempio Operand Stack (2) dopo i_load0 dopo i_load1 0 100 local variables 1 98 0 100 2 local variables 0 100 local variables 1 98 1 98 2 2 198 operand stack 100 0 100 local variables operand stack 100 1 98 dopo i_add operand stack dopo i_store2 98 2 operand stack 198
Frame – Frame data Contiene le informazioni necessarie a runtime per l’esecuzione di un metodo: • un puntatore al runtime Constant Pool (per realizzare il late binding, ma non solo…) • informazioni per il return da un metodo • un riferimento alla tavola delle eccezioni nella method area
PC registers • Ogni thread ha il proprio pc (program counter) register • Durante l’esecuzione di un metodo il pc register contiene l’indirizzo dell’istruzione corrente eseguita dal thread • Se il metodo non è native il pc register contiene l’indirizzo dell’istruzione della macchina virtuale correntemente eseguita; se il metodo è native il valore del pc register è indefinito
Native method stacks • Utilizzati dalla JVM per consentire l’esecuzione di codice nativo (diverso da Java) • Quando un thread invoca un metodo nativo, la JVM, invece di fare il push di un nuovo frame sul Java Stack, “crea” un collegamento direttamente con lo stack del metodo invocato
DEFINIZIONE DI CLASS FILE Il class file è un file in cui vengono definiti le rappresentazioni di una classe o interfaccia ed è costituito da un flusso di 8 byte.
LA STRUTTURA DI UN CLASS FILE ClassFile { u4 magic; 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]; }
I DESCRITTORI Un descrittore è una stringa che rappresenta il tipo di campo o metodo. I descrittori sono rappresentati nel class file format usando UTF-8 string e seguono una determinata grammatica
FIELD DESCRIPTORS Un field descriptor rappresenta il tipo di una classe, istanza, o variabile locale
GRAMMATICA DI UN FIELD DESCRIPTOR FieldDescriptor: FieldType ComponentType: FieldType FieldType: BaseTypeObjectType ArrayType BaseType: B C D F I J S Z ObjectType:L <classname> ; ArrayType:[ ComponentType
METHOD DESCRIPTORS Un method descriptors rappresenta i parametri che il metodo prende e i valori che esso ritorna: MethodDescriptor: (ParameterDescriptor)ReturnDescriptor
METHOD DESCRIPTOR Un parameter descriptor rappresenta un parametro passato ad un metodo: ParameterDescriptor: FieldType
METHOD DESCRIPTOR Un return descriptor rappresenta il tipo di valore ritornato da un metodo ReturnDescriptor: FieldType V Il carattere V indica che il metodo non retorna nessun valore (void)
CONSTANT POOL TABLE Le istruzioni della java virtual machine non si affidano al layout di classi, interfacce, istanze di classe ma si riferiscono ad informazioni simboliche presenti nella constant_pool table dove ogni entry della tabella ha il seguente formato: cp_info { u1 tag; u1 info[]; }
La struttura CONSTANT_Class_info L a struttura CONSTANT_Class_info e’ utilizzata per rappresentare una classe o un’interfaccia e ha la seguente struttura: CONSTANT_Class_info { u1 tag; u2 name_index; }
Le strutture CONSTANT_Fieldref_info, CONSTANT_Methodref_info, e CONSTANT_InterfaceMethodref_info I campi, i metodi di una classe e i metodi di un interfaccia sono rappresentati dalle seguenti strutture: CONSTANT_Fieldref_info { u1 tag; u2 class_index; u2 name_and_type_index; } CONSTANT_Methodref_info { u1 tag; u2 class_index; u2 name_and_type_index; } CONSTANT_InterfaceMethodref_info { u1 tag; u2 class_index; u2 name_and_type_index; }
La struttura CONSTANT_NameAndType_info • La struttura CONSTANT_NameAndType_info e’ usata • per rappresentare un campo o un metodo, senza indicare • a quale tipo di interfaccia o classe appartiene. • CONSTANT_NameAndType_info { u1 tag; • u2 name_index; • u2 descriptor_index; }
La struttura CONSTANT_Utf8_info • La struttura CONSTANT_Utf8_info e’ utilizzata per • rappresentare valori di stringa costanti • CONSTANT_Utf8_info { u1 tag; • u2 length; • u1 bytes[length]; • }
I CAMPI • Ogni campo della classe e’ descritto dalla struttura • field_info. Due campi all’interno della stessa classe non • possono avere lo stesso nome e quindi lo stesso • descrittore. • field_info { u2 access_flags; • u2 name_index; • u2 descriptor_index; • u2 attributes_count; • attribute_info attributes[attributes_count]; • }
I METODI • Ogni metodo, incluso ogni istanza di inizializzazione di metodo, ogni metodo di inizializzazione di interfaccia e di classe, e’ descritta dalla struttura method_info. Due metodi all’interno della stessa classe non possono avere lo stesso nome e quindi lo stesso descrittore. • method_info { u2 access_flags; • u2 name_index; • u2 descriptor_index; • u2 attributes_count; • attribute_info attributes[attributes_count]; • }
LE ISTRUZIONI DELLA JAVA VIRTUAL MACHINE Le istruzioni della java virtual machine consistono di un opcode che specificano quale operazione deve essere eseguita, seguita da uno o piu' operandi che includono su quali valori agisce l'istruzione.
CLASSIFICAZIONE DELLEISTRUZIONI • Abbiamo diverse classi di istruzioni: • Load e strore dello stack • Aritmetiche • Conversioni di tipo • Creazioni e manipolazioni di oggetti • Di controllo • Invocazione di metodi • ….
L’ISTRUZIONE NEW L’istruzione new e’ utilizzata per creare un nuovo oggetto. New = 187 (0xbb) Gli unsigned indexbyte1 e indexbyte2 sono usati per costruire un indice nella Constant pool della classe corrente dove il valore dell’indice è (indexbyte1 << 8) | indexbyte2 .
UN ESEMPIO DI NEW ;This example creates a new StringBuffer object. ;This is like the Java code: ; ; StringBuffer x = new StringBuffer(); ; 1. use new to create a new object reference new java/lang/StringBuffer ; 2. dup the object reference and call its constructor dup invokespecial java/lang/StringBuffer/<init>()V ; 3. assign object reference on the stack to a local variable astore_1 ; local variable 1 now contains a StringBuffer object, ; ready for use
L’ISTRUZIONE INVOKESPECIAL L’istruzione invokespecial invoca metodi d’istanza invokespecial = 183 (0xb7) Gli unsigned indexbyte1 e indexbyte2 sono usati per costruire un indice nella Constant pool della classe corrente dove il valore dell’indice è (indexbyte1 << 8) | indexbyte2.
UN ESEMPIO DI INVOKESPECIAL class Example { // override equals public boolean equals(Object x) { // call Object's version of equals return super.equals(x); } } aload_0 ; push 'this' onto the stack aload_1 ; push the first argument (i.e. x) onto the stack ; now invoke Object's equals() method. invokespecial java/lang/Object/equals(Ljava/lang/Object;)Z