L’architettura della
Java Virtual Machine
Implementazione di Linguaggi
A.A. 2003/2004
di Gualdani Alessandro
1
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
2
Cos’è la JVM

(2)
È un interprete del bytecode:
 la
fase di compilazione “traduce” i
sorgenti java in un linguaggio
intermedio, il bytecode, memorizzato
nei class files
A.java
B.java
C.java
Java
compiler
bytecode A.class
B.class
C.class
3
Cos’è la JVM
(3)
A
runtime la JVM esegue il codice
contenuto nei class files
A.class
B.class
C.class
JVM
class
loader
Java API class files
bytecode
execution
engine
native method invocations
Host operating system
4
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)
5
Tipi di dato
32 bit
64 bit
8 bit
16 bit
32 bit
64 bit
16 bit
6
Architettura JVM
7
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
8
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”
9
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

10
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, …)
11
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
12
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

13
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
14
Heap





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:
Object reference 1
ptr to class data
instance data
Class 1
data
Object reference 2
ptr to class data
instance data
Class 2
data
Heap
Method area
15
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

16
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.
17
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)
18
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)

19
Esempio Operand Stack
Supponiamo l’esecuzione del
seguente frammento di codice:
Dopo l’esecuzione della prima
riga di codice, il frame si
presenta così:
(1)
int a=100; int b=98; int c;
………
c=a+b;
0 100
local
1 98
variables
2
operand
stack
L’istruzione c=a+b; viene convertita nelle seguenti istruzioni:
iload_0
iload_1
iadd
istore_2
// push l’intero contenuto in local variable 0
// push l’intero contenuto in local variable 1
// pop due interi, li somma, push del risultato
// pop di un intero e store in local variable 2
20
Esempio Operand Stack
dopo i_load0
0 100
local
1 98
variables
2
operand
stack
100
dopo i_add
0 100
local
1 98
variables
2
operand
stack
198
(2)
dopo i_load1
0 100
local
1 98
variables
2
operand
stack
100
98
dopo i_store2
0 100
local
1 98
variables
2 198
operand
stack
21
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
22
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
23
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

24
IL CLASS FILE FORMAT
di D’Angelo Paolo
25
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.
26
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];
}
27
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
28
FIELD DESCRIPTORS
Un field descriptor rappresenta il tipo
di una classe, istanza, o variabile
locale
29
GRAMMATICA DI UN FIELD
DESCRIPTOR
FieldDescriptor:
FieldType
ComponentType:
FieldType
FieldType:
BaseType ObjectType
ArrayType
BaseType:
B
C
D
F
I
J
S
Z
ObjectType:
L <classname> ;
ArrayType:
[ ComponentType
30
GRAMMATICA DI UN FIELD
DESCRIPTOR
Caratteri BaseType
Tipo
Interpretazione
B
Byte
Signed byte
C
Char
Unicode character
D
Double
Double-precision
floating-point value
F
Float
Single precision
floating-point value
I
Int
Interger
J
Long
Long integer
L<classname>;
Reference
An instace di class
<classname>
S
Short
Signed short
Z
Boolean
True or false
[
reference
One array dimension
31
METHOD DESCRIPTORS
Un method descriptors rappresenta i
parametri che il metodo prende e i
valori che esso ritorna:
MethodDescriptor:
(ParameterDescriptor)ReturnDescriptor
32
METHOD DESCRIPTOR
Un parameter descriptor rappresenta
un parametro passato ad un
metodo:
ParameterDescriptor:
FieldType
33
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)
34
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[];
}
35
CONSTANT POOL
ConstantType
Valore
CONSTANT_Class
7
CONSTANT_Fieldref
9
CONSTANT_Methodref
10
CONSTANT_InterfaceMetho
dref
11
CONSTANT_String
8
CONSTANT_Integer
3
CONSTANT_Float
4
CONSTANT_Long
5
CONSTANT_Double
6
CONSTANT_NameAndType
12
36
UN ESEMPIO DI CONSTANT
POOL TABLE
37
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;
}
38
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;
}
39
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;
}
40
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];
}
41
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];
42
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];
}
43
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.
44
IL FORMATO DELLE
ISTRUZIONI
OP CODE
OPERAND1
OPERAND2
……
45
CLASSIFICAZIONE DELLE
ISTRUZIONI
Abbiamo diverse classi di istruzioni:
•Load e strore dello stack
•Aritmetiche
•Conversioni di tipo
•Creazioni e manipolazioni di oggetti
•Di controllo
•Invocazione di metodi
•….
46
L’ISTRUZIONE NEW
L’istruzione new e’ utilizzata per creare un nuovo oggetto.
New
Indexbyte1
indexbyte2
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 .
47
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
48
L’ISTRUZIONE
INVOKESPECIAL
L’istruzione invokespecial invoca metodi d’istanza
invokespecial
indexbyte1
indexbyte2
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.
49
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
aload_1
invokespecial
; push 'this' onto the stack
; push the first argument (i.e. x) onto the stack
; now invoke Object's equals() method.
java/lang/Object/equals(Ljava/lang/Object;)Z
50
L’ISTRUZIONE
INVOKESTATIC
L’istruzione invoke static invoca un metodo di classe statico.
invokestatic
indexbyte1
indexbyte2
invokestatic = 184 (0xb8)
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.
51
UN ESEMPIO DI
INVOKESTATIC
System.exit(1);
iconst_1
invokestatic
; push 1 onto the stack.
; now call System.exit()
java/lang/System/exit(I)V
52
L’ISTRUZIONE
INVOKEINTERFACE
L’istruzione invoca il metodo d’interfaccia
Invokeinterface
Indexbyte1
Indexbyte2
Count
0
invokeinterface = 185 (0xb9)
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 .
53
UN ESEMPIO DI
INVOKEINTERFACE
void test(Enumeration enum)
{
boolean x = enum.hasMoreElements(); ... }
aload_1
invokeinterface
istore_2
; push local variable 1 (i.e. the enum object) onto the stack
; call hasMoreElements()
java/util/Enumeration/hasMoreElements()Z 1
; store the boolean result in local variable 2 (i.e. x)
54
L’ISTRUZIONE
INVOKEVIRTUAL
L’istruzione invokevirtual invoca l’istanza di un metodo
invokevirtual
indexbyte1
indexbyte2
invokevirtual = 182 (0xb6)
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.
55
UN ESEMPIO DI
INVOKEVIRTUAL
Object x;
...
x.equals("hello");
aload_1
ldc "hello"
invokevirtual
; push local variable 1 (i.e. 'x') onto stack
; push the string "hello" onto stack
; invoke the equals method I
java/lang/Object/equals(Ljava/lang/Object;)Z
; the boolean result is now on the stack
56
Esempio
import java.lang.*;
class Padre
{ protected String s;
public Padre(){}
public class Main
{ public static void main(String args[])
{ Padre p=new Padre("Padre");
Figlio f=new Figlio("Figlio");
p=f; p.stampa();
}
}
public Padre(String s) { this.s=s;}
public void stampa()
{ System.out.println("Stringa stampata: "+s+"\n");
}
}
class Figlio extends Padre
{ public Figlio(String s) { this.s=s;}
}
57
Esempio –

public Padre(String s)
Il costruttore della classe Padre, public
Padre(String s), si traduce nelle seguenti
istruzioni:
public Padre( java.lang.String locVar_1)
{ aload_0
this
//load 'reference' (object) from locVar #0
invokespecial java.lang.Object.<init>
//invoke instance method
aload_0
this
//load 'reference' (object) from locVar #0
aload_1
locVar_1
//load 'reference' (object) from locVar #1
putfield
Padre.s
//set field value in object
return
//return 'void' from method
}
58
Esempio –

public Figlio(String s)
Il costruttore della classe Figlio si
traduce nelle seguenti istruzioni:
public Figlio( java.lang.String locVar_1)
{ aload_0
this
//load 'reference' (object) from locVar #0
invokespecial Padre.<init>
//invoke instance method
aload_0
this
//load 'reference' (object) from locVar #0
aload_1
locVar_1
//load 'reference' (object) from locVar #1
putfield
Figlio.s
//set field value in object
return
//return 'void' from method
}
59
Esempio –

public void stampa()
L’operazione stampa() si traduce nelle seguenti
istruzioni:
public void stampa()
{getstatic
java.lang.System.out
//get 'static' field value from class
new
java.lang.StringBuffer
//Create new object
dup
//duplicate top operand stack word
invokespecial java.lang.StringBuffer.<init> //invoke instance method
ldc
"Stringa stampata: "
//push item from constant pool
invokevirtual java.lang.StringBuffer.append //invoke virtual method
aload_0
this
//load 'reference' (object) from locVar #0
getfield
Padre.s
//get field value from object.
invokevirtual java.lang.StringBuffer.append //invoke virtual method
ldc
"\n"
//push item from constant pool
invokevirtual java.lang.StringBuffer.append //invoke virtual method
invokevirtual java.lang.StringBuffer.toString //invoke virtual method
invokevirtual java.io.PrintStream.println
//invoke virtual method
return
//return 'void' from method
60
}
Esempio – public static void main(String[] args)

Il main si traduce nelle seguenti istruzioni:
public static void main( java.lang.String[] args)
{ java.lang.Object locVar_1; (object p)
java.lang.Object locVar_2; (object f)
new
Padre
dup
ldc
"Padre"
invokespecial Padre.<init>
astore_1
locVar_1
new
Figlio
dup
ldc
"Figlio"
invokespecial Figlio.<init>
astore_2
locVar_2
aload_2
locVar_2
astore_1
locVar_1
aload_1
locVar_1
invokevirtual Padre.stampa
return
}
//Create new object
//duplicate top operand stack word
//push item from constant pool
//invoke instance method
//store 'reference' (object p) into local variable #1
//Create new object
//duplicate top operand stack word
//push item from constant pool
//invoke instance method
//store 'reference' (object f) into locVar#2
//load 'reference' (object f) from locVar #2
//store 'reference' (object f) into locVar #1
//load 'reference' (object p) from locVar #1
//invoke virtual method
//return 'void' from method
61
Esempio –

Riferimenti simbolici
Nell’esempio, per una maggiore
chiarezza, sono stati considerati i
nomi dei metodi: in realtà tutte le
istruzioni della JVM agiscono su
riferimenti simbolici; ad esempio
nella traduzione del metodo void
stampa() si è scritto
invokevirtual Padre.stampa
In realtà l’istruzione “vera” è
invokevirtual #8
62
Esempio –
Constant Pool
La parte del Constant Pool relativa alla risoluzione
del metodo stampa è la seguente:
idx: 2 CONSTANT_Class name_index=20
idx: 8 CONSTANT_Methodref class_index=2 , name_and_type_index=23
idx: 12 CONSTANT_Utf8 value="()V"
idx: 20 CONSTANT_Utf8 value="Padre"
idx: 23 CONSTANT_NameAndType name_index=27 , descriptor_index=12
idx: 27 CONSTANT_Utf8 value="stampa"
63
Bibliografia
Tim Lindholm – Frank Yellin
The Java Virtual Machine
Specification Second Edition
ADDISON-WESLEY
 Bill Venners
Inside the Java Virtual Machine

64