JVM (Java Virtual Machine) acționează ca un motor de rulare pentru a rula aplicații Java. JVM este cel care de fapt apelează principal metodă prezentă într-un cod Java. JVM face parte din JRE (Java Runtime Environment).
Aplicațiile Java se numesc WORA (Write Once Run Anywhere). Aceasta înseamnă că un programator poate dezvolta cod Java pe un sistem și se poate aștepta să ruleze pe orice alt sistem compatibil Java fără nicio ajustare. Toate acestea sunt posibile datorită JVM.
Când compilam un .java fişier, .clasă fișiere (conține codul octet) cu aceleași nume de clasă prezente în .java fișierele sunt generate de compilatorul Java. Acest .clasă fișierul trece în diferiți pași atunci când îl rulăm. Acești pași împreună descriu întreaga JVM.
Subsistem de încărcare de clasă
Este responsabil în principal pentru trei activități.
- Se încarcă
- Legătura
- Inițializare
Se încarcă: Încărcătorul de clasă citește fișierul . clasă fișier, generați datele binare corespunzătoare și salvați-le în zona metodei. Pentru fiecare .clasă fișier, JVM stochează următoarele informații în zona metodei.
- Numele complet calificat al clasei încărcate și clasa părinte imediată a acesteia.
- Fie că .clasă fișierul este legat de Class sau Interface sau Enum.
- Modificator, variabile și informații despre metodă etc.
După încărcarea .clasă fișier, JVM creează un obiect de tip Class pentru a reprezenta acest fișier în memoria heap. Vă rugăm să rețineți că acest obiect este de tip Clasă predefinită în java.lang pachet. Aceste obiecte Clasă pot fi utilizate de către programator pentru a obține informații la nivel de clasă, cum ar fi numele clasei, numele părintelui, metode și informații variabile etc. Pentru a obține această referință la obiect putem folosi getClass() Metodă de Obiect clasă.
Java
instanță java a
// A Java program to demonstrate working> // of a Class type object created by JVM> // to represent .class file in memory.> import> java.lang.reflect.Field;> import> java.lang.reflect.Method;> // Java code to demonstrate use> // of Class object created by JVM> public> class> Test {> > public> static> void> main(String[] args)> > {> > Student s1 => new> Student();> > // Getting hold of Class> > // object created by JVM.> > Class c1 = s1.getClass();> > // Printing type of object using c1.> > System.out.println(c1.getName());> > // getting all methods in an array> > Method m[] = c1.getDeclaredMethods();> > for> (Method method : m)> > System.out.println(method.getName());> > // getting all fields in an array> > Field f[] = c1.getDeclaredFields();> > for> (Field field : f)> > System.out.println(field.getName());> > }> }> // A sample class whose information> // is fetched above using its Class object.> class> Student {> > private> String name;> > private> int> roll_No;> > public> String getName() {> return> name; }> > public> void> setName(String name) {> this> .name = name; }> > public> int> getRoll_no() {> return> roll_No; }> > public> void> setRoll_no(> int> roll_no)> > {> > this> .roll_No = roll_no;> > }> }> |
>
>Ieșire
Student getName setName getRoll_no setRoll_no name roll_No>
Notă: Pentru fiecare încărcat .clasă dosar, numai unu este creat obiectul clasei.
Student s2 = new Student(); // c2 will point to same object where // c1 is pointing Class c2 = s2.getClass(); System.out.println(c1==c2); // true>
Conectare: Efectuează verificarea, pregătirea și (opțional) rezoluția.
- Verificare : Asigură corectitudinea .clasă fișier, adică verifică dacă acest fișier este formatat corect și generat de un compilator valid sau nu. Dacă verificarea eșuează, obținem o excepție de timp de execuție java.lang.VerifyError . Această activitate este realizată de componenta ByteCodeVerifier. Odată ce această activitate este finalizată, fișierul de clasă este gata pentru compilare.
- Pregătirea : JVM alocă memorie pentru variabilele statice de clasă și inițializează memoria la valorile implicite.
- Rezoluţie : Este procesul de înlocuire a referințelor simbolice din tip cu referințe directe. Se face prin căutarea în zona metodei pentru a localiza entitatea la care se face referire.
Inițializare: În această fază, toate variabilele statice sunt alocate cu valorile lor definite în cod și bloc static (dacă există). Aceasta se execută de sus în jos într-o clasă și de la părinte la copil în ierarhia clasei.
În general, există trei clase de încărcătoare:
- Încărcător de clasă Bootstrap : Fiecare implementare JVM trebuie să aibă un încărcător de clasă bootstrap, capabil să încarce clase de încredere. Încarcă clasele de bază API java prezente în JAVA_HOME/jre/lib director. Această cale este cunoscută în mod popular ca calea bootstrap. Este implementat în limbi native precum C, C++.
- Încărcător clasa de extensie : Este un copil al încărcării clasei bootstrap. Încarcă clasele prezente în directoarele de extensii JAVA_HOME/jre/lib/ext (Calea extensiei) sau orice alt director specificat de proprietatea de sistem java.ext.dirs. Este implementat în java de către sun.misc.Launcher$ExtClassLoader clasă.
- Încărcător de clasă de sistem/aplicație : Este un copil al încărcătorului clasei de extensie. Este responsabil să încarce clase din calea clasei aplicației. Utilizează intern variabila de mediu care a fost mapată la java.class.path. Este, de asemenea, implementat în Java de către sun.misc.Launcher$AppClassLoader clasă.
Java
piton sau
// Java code to demonstrate Class Loader subsystem> public> class> Test {> > public> static> void> main(String[] args)> > {> > // String class is loaded by bootstrap loader, and> > // bootstrap loader is not Java object, hence null> > System.out.println(String.> class> .getClassLoader());> > // Test class is loaded by Application loader> > System.out.println(Test.> class> .getClassLoader());> > }> }> |
unghiuri adiacente
>
>Ieșire
null jdk.internal.loader.ClassLoaders$AppClassLoader@8bcc55f>
Notă: JVM urmează principiul Delegare-Ierarhie pentru a încărca clase. Încărcătorul clasei de sistem delege cererea de încărcare la încărcătorul clasei de extensie și cererea de delegare a încărcării clasei de extensie către încărcătorul clasei de bootstrap. Dacă o clasă găsită în calea boot-strap, clasa este încărcată, altfel cererea se transferă din nou la încărcătorul de clasă de extensie și apoi la încărcătorul de clasă de sistem. În cele din urmă, dacă încărcătorul de clasă de sistem nu reușește să încarce clasa, atunci obținem excepția de rulare java.lang.ClassNotFoundException .
Memoria JVM
- Zona metodei: În zona metodelor, toate informațiile la nivel de clasă, cum ar fi numele clasei, numele clasei părinte imediate, informațiile despre metode și variabile etc., sunt stocate, inclusiv variabilele statice. Există o singură zonă de metodă per JVM și este o resursă partajată.
- Zona de grămadă: Informațiile despre toate obiectele sunt stocate în zona heap. Există, de asemenea, o zonă Heap per JVM. Este, de asemenea, o resursă comună.
- Zona stivei: Pentru fiecare fir, JVM creează o stivă de rulare care este stocată aici. Fiecare bloc al acestei stive se numește înregistrare de activare/cadru de stivă care stochează apelurile de metode. Toate variabilele locale ale acelei metode sunt stocate în cadrul lor corespunzător. După ce un fir de execuție se termină, stiva sa de rulare va fi distrusă de JVM. Nu este o resursă comună.
- Registre PC: Adresa de stocare a instrucțiunii de execuție curente a unui fir. Evident, fiecare thread are registre PC separate.
- Stive de metode native: Pentru fiecare thread, se creează o stivă nativă separată. Stochează informații despre metoda nativă.
Motor de execuție
Motorul de execuție execută .clasă (cod octet). Citește codul de octet linie cu linie, folosește datele și informațiile prezente în diferite zone de memorie și execută instrucțiuni. Poate fi clasificat în trei părți:
- Interpret : interpretează bytecode linie cu linie și apoi se execută. Dezavantajul aici este că atunci când o metodă este apelată de mai multe ori, de fiecare dată este necesară interpretarea.
- Compilator Just-In-Time (JIT) : Este folosit pentru a crește eficiența unui interpret. Compilează întregul bytecode și îl schimbă în cod nativ, astfel încât ori de câte ori interpretul vede apeluri repetate de metodă, JIT oferă cod nativ direct pentru acea parte, astfel încât reinterpretarea nu este necesară, astfel eficiența este îmbunătățită.
- Colector de gunoi : Distruge obiectele nereferite. Pentru mai multe despre Garbage Collector, consultați Colector de gunoi .
Interfață nativă Java (JNI):
Este o interfață care interacționează cu Native Method Libraries și oferă bibliotecile native (C, C++) necesare execuției. Acesta permite JVM să apeleze biblioteci C/C++ și să fie apelat de bibliotecile C/C++ care pot fi specifice hardware-ului.
Biblioteci de metode native:
Este o colecție de biblioteci native (C, C++) care sunt cerute de Execution Engine.