Sunteți pe pagina 1din 24

Mașina virtuală java

Jvm - java virtual machine


Arhitectura
JVM
• Toate clasele într-o aplicație Java sunt încărcate folosind clase
speciale derivate din clas java.lang.Classloader
• Bootstrap Class Loader este responsabil pentru incarcarea claselor
Java de baza rt.jar (java.*, javax.* etc.) - JAVA_HOME/jre/lib
directory
• Extension Class Loader este responsabil cu incarcarea claselor din
bibliotecile extinse (lib\ext)
• Application Class Loader este responsabil cu incarcarea claselor
utilizator din aplicație
• Interpretorul - interpreteaza si execută codul de octeți. Este lent din
cauza reinterpretarii codului care se repeta
• Just-In-Time(JIT) compiler - transforma codul de octeti in cod
masina pentru metode care se executa repetat
Structura alocării memoriei
Structurarea memoriei unei aplicatii: Stiva, Heap, Method Area
 Stiva. Este impartită pe thread-uri astfel:
 Program Counter Register memoreaza adresa instrucțiunii curente
de executat
 JVM Stack - variabile locale, parametrii de metode, valori returnate si
rezultate parțiale
 Native Method Stack este zona alocată pentru stivele asociate
metodelor native din cadrul unui Thread
 Heap este zona de memorie în care au loc alocările de spațiu pentru
obiecte și masive. Este comună pentru toate thread-urile procesului.
Este gestionată în sensul eliberării spațiului ocupat de către obiecte care
nu mai sunt folosite de către GC
 MA este o zonă structurată per clasă și este echivalentă zonei de cod
asociată unei aplicații clasice C, C++. Este partajată în comun de toate
threadurile procesului. Stochează definiții de clase și interfețe, codul
constructorilor și metodelor, constantele și variabilele statice.
• Runtime Constant Pool este zona de memorie din Method Area in care sunt
incarcate toate constantele simbolice ale claselor. Acestea reprezinta datele
associate codului de octeti al claselor. Datele din Constant Pool sunt memorate
sub forma unei tabele de simboluri.
Ciclul de viata al unei clase
Se refera la existenta clasei in memorie
 Incarcare – Load - Incarcarea codului de octeti al clasei (byte code)
 Legare – Link
 Verificare – Verify - Verificarea codului de octeti
 Alocare – Prepare - Alocarea spatiului de memorie pentru clasa in Memory Area
 Rezolvarea referintelor simbolice din Constant Pool – Resolve – Transformarea
referintelor simbolice in referinte de memorie
 Initializare – Initialize - Initializarea variabilelor statice si executarea
blocurilor statice de initializare
 Instantiere – Instantiation - Instantierea obiectelor
 Eliberarea spatiului ocupat de obiecte – Collection
 Finalizarea obiectelor - Finalize
 Eliberarea spatiului ocupat de clasa - Unload
Colectarea

Mecanism prin care JVM isi realizeaza managementul memoriei


Lansarea voluntara a colectarii se poate realiza prin metodele statice ale
clasei utilitare System:

public static void gc(); // Lansarea voluntara a GC in incercarea de


colectare a tuturor obiectelor fara referinta

public static void runFinalization(); // lansarea metodei finalize() pt.


obiectele colectate pentru care nu s-a rulat finalize(). Reda controlul
apelatorului dupa finalizare

Exp (E_GCSimplificat)
Clasa Object
• protected object clone() throws clonenotsupportedexception; // returneaza o clona a
obiectului curent
• public boolean equals(object obj); // arata daca obiectul current este egal cu cel specificat.
pentru un obiect non-null metoda are proprietatile: reflexivitate, simetrie, tranzitivitate,
consistenta si non-egalitate cu null. implementarea implicita pentru object: intoarce true daca
obiectul current este acelasi cu obj.
• protected void finalize() throws throwable ; // metoda invocata de colectorul de reziduuri la
disponibilizarea obiectului
• public final class getclass(); // furnizeaza instanta de tip class asociata obiectului curent
• public final void notify() ; // scoate din starea de asteptare un fir introdus in asteptare prin
obiectul monitor curent (programare concurenta)
• public final void notifyall() ; // idem pentru toate firele
• public final void wait() throws interruptedexception ; // trecere in stare de asteptare a firului
curent. metoda este invocata intr-un context concurential
• public final void wait(long timeout) throws interruptedexception ; //idem dar se specifica o
cuanta de timp exprimata ia milisecunde pentru starea de asteptare
• public final void wait(long timeout, int nanos) throws interruptedexception; //idem
 public String toString() ; // descriere de tip string a obiectului curent
Descrierea implicita este:
getClass().getName() + '@' + Integer.toHexString(hashCode())
 public int hashCode() ; // Intoarce un cod hash asociat obiectului, cod
care sa poata fi utilizat in tabele de dispersie. Conventiile de generare a
codului hash sunt:
 codul unui obiect nu se schimba pe parcursul unei executii
 doua obiecte egale in sensul metodei equals, au coduri egale
 doua obiecte inegale conform equals nu trebuie sa aiba neaparat coduri distincte
Pentru a respecta aceste reguli este necesara suprascrierea metodei
hashCode atunci cand se suprascrie metoda equals.
Tratarea exceptiilor
Erorile se impart in doua tipuri: checked si unchecked dupa cum tratarea lor este obligatorie sau nu
(adica trebuie mentionate in clauzele throws ale metodelor/constructorilor si trecute prin blocul try-
catch).
Ierarhia:
Throwable - Superclasa tuturor claselor de erori
Error - Erori grave de tip unchecked cauzate de regula de mediu
Exception - Exceptii corespunzand unor erori obisnuite de tip checked mai putin cele de tip
RuntimeException care sunt de tip unchecked si sunt generate de JVM
Metode ale clasei Throwable

public String getMessage() ; // intoarce mesajul de tip String asociat


erorii
public StackTraceElement[] getStackTrace(); // intoarce elementele din
stiva de executie reprezentand metode aflate in executie la momentul
aruncarii exceptiei
public String toString() ; // intoarce mesajul de eroare si numele clasei
public Throwable getCause(); // intoarce cauza care a generat eroarea
atunci cand eroarea a fost provocata de o alta eroare.
try{
// secventa
}
catch(ClasaExceptii1 e1){secventa1}
...
catch(ClasaExceptiiN eN){secventaN}
finally{secventaFinal}

Exp (E_Exceptii)
Clonarea obiectelor
• Obiectele clonabile trebuie sa fie instante ale unor clase care implementeaza interfata
Cloneable;
protected Object clone() throws CloneNotSupportedException; // shallow copy

public Object clone() throws CloneNotSupportedException {


try {
return super.clone(); // shallow copy
// instantiere obiect nou - deep copy
}
catch(CloneNotSupportedException e){
System.out.println("Eroare la clonare!"+e);
return this;
}
}

Exp (E_Clonare)
Java Native Interface (JNI)
• Este o interfata Java pentru cod nativ.
• Avantaje: reutilizare de cod, performante imbunatatite ca timp de executie.
• Este dezvoltata pentru utilizare cod C++ si C.

Etapele construirii unei aplicatii JNI:


1. Scrierea clasei Java care utilizeaza metode native
2. Construirea fisierului header C++ sau C in care sunt descrise functiile prototip
corespunzatoare metodelor native. Se foloseste utilitarul javah:
javah numeFisierClass
Functia prototip va fi:
JNIEXPORT tip JNICALL Java_numeClasa_metoda(JNIEnv *env, jobject obj,
listaParametrii);
unde:
• tip - tipul functiei; numeClasa - este numele calificat al clasei; metoda - numele
metodei; listaParametrii - lista parametriilor metodei native
• JNIEnv este o structură care permite accesul la funcțiile JNI, un pointer la o
tabelă de pointeri către funcții JNI
• obj - referinta la obiectul Java
• JNIEXPORT, JNICALL - macrodefinitii utilizate pentru conformitatea codului
C++ (conventii de apel, parametrizari pentru compilarea si linkedidarea codului
C++)
3. Implementarea functiilor C++/C si construirea bibliotecii cu incarcare dinamica
dll.
#include <jni.h>
#include "numeFisierPrototip.h"
JNIEXPORT tip JNICALL Java_numeClasa_metoda(JNIEnv *env, jobject obj,
listaParametrii)
{ ....
[return;]
}
4. Incarcarea bibliotecii dinamice in aplicatia Java si rularea aplicatiei.
System.loadLibrary(numeDll)
Tipuri definite in JNI
• Tipuri definite la nivelul "win\jni_mh.h"
• typedef long jint;
• typedef __int64 jlong;
• typedef signed char jbyte;

• Tipuri definite la nivel "jni.h"


• typedef unsigned char jboolean;
• typedef unsigned short jchar;
• typedef short jshort;
• typedef float jfloat;
• typedef double jdouble;
• typedef jint jsize;
Tipuri de date JNI si maparea tipurilor

Tip Java Tip JNI Descriere


boolean jboolean 8 bits, unsigned
byte jbyte 8 bits, signed
char jchar 16 bits, unsigned
double jdouble 64 bits
float jfloat 32 bits
int jint 32 bits, signed
long jlong 64 bits, signed
short jshort 16 bits, signed
void void N/A
Identificatori de tipuri
Tip Java Signature
Se referă la identificatorii utilizați in boolean Z
semnătura metodelor.
byte B
Exemple:
char C
Metoda Semnatura
double D
void f1() ()V
int f2(int, long) (IJ)I
float F
boolean f3(int[]) ([I)B int I
double f4(String, int) (Ljava/lang/String;I)D long J
void f5(int, String [], void V
(I[Ljava/lang/String;C)V
char) object Lnume_calificat_clasa;
tip[] [tip
metoda ( tip_argumente) tip_returnat
Lucrul cu masive unidimensionale
• Sunt definite 9 tipuri de masive unidimensionale, 8 pentru tipurile primitive și unul pentru
obiecte: jintArray, jbyteArray, jshortArray, jlongArray, jfloatArray, jdoubleArray,
jcharArray, jbooleanArray, jobjectArray
• Functii de lucru cu masive unidimensionale:
jsize GetArrayLength(JNIEnv *env, jarray array); // Dimensiune masiv
ArrayType New<PrimitiveType>Array(JNIEnv *env, jsize length); // Alocare.
Exemplu: jintArray NewIntArray(JNIEnv *env, jsize len);
jobjectArray NewObjectArray(JNIEnv *env, jsize length, jclass elementClass, jobject
initialElement); // Alocare masiv obiecte
NativeType *Get<PrimitiveType>ArrayElements(JNIEnv *env, ArrayType array,
jboolean *isCopy); // Preluare elemente. Exemplu pentru int:
jint *GetIntArrayElements(JNIEnv *env, jintArray array, jboolean *isCopy)
jobject GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index); // preluare
un element cu indexul precizat
SetTipArrayRegion(JNIEnv *env, jtipArray a, jsize start, jsize len, const jtip *buf);
// Familie de functii pentru copiere valori dintr-un buffer intr-un masiv
Exemplu: SetIntArrayRegion(JNIEnv *env, jintArray a, jsize start, jsize len, const
jint *buf)
void SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index,
jobject value); // Stabilire valoare pentru obiectul de pe pozitia index
void Get<PrimitiveType>ArrayRegion(JNIEnv *env, ArrayType array,
jsize start, jsize len, NativeType *buf); // Familie de functii care copie o regiune
dintr-un masiv într-un buffer
Accesarea campurilor clasei in functiile C++

Accesarea campurilor si metodelor clasei se face prin mediul JNI.


Accesarea campurilor presupune:
• Obtinere referinta la clasa:
jclass thisClass = env->GetObjectClass(obj);
• Obtinerea identificatorului de camp:
jfieldID fidField = env->GetFieldID(thisClass, "numeCamp",
"IdentificatorDeTip");
• Obtinerea valorii campului:
tip nume = env->GetTipField(obj, fidField);
Accesarea metodelor clasei in functiile C++
Accesarea metodelor presupune:
• Obtinere referinta la clasa:
jclass thisClass = env->GetObjectClass(obj);
• Obtinerea identificatorului de metoda:
jmethodID myMethod = env->GetMethodID(thisClass,
"numeMetoda", "IdentificatorDeTip");
• Invocarea metodei:
env->CallTipMethod(obj, myMethod);

Exp (E_JNI, E_JNI_Cpp)

S-ar putea să vă placă și