JavaRush /Java Blogu /Random-AZ /Dərslər JVM-ə necə yüklənir
Aleksandr Zimin
Səviyyə
Санкт-Петербург

Dərslər JVM-ə necə yüklənir

Qrupda dərc edilmişdir
Proqramçı işinin ən çətin hissəsi tamamlandıqdan və “Salam Dünya 2.0” tətbiqi yazıldıqdan sonra paylama dəstini yığmaq və müştəriyə və ya heç olmasa sınaq xidmətinə ötürmək qalır. Dağıtımda hər şey olması lazım olduğu kimidir və proqramımızı işə saldığımız zaman Java Virtual Maşın səhnəyə çıxır. Sirr deyil ki, virtual maşın bayt kodu şəklində sinif fayllarında təqdim olunan əmrləri oxuyur və onları təlimatlar kimi prosessora çevirir. Bayt kodunun virtual maşına daxil olması sxemi haqqında bir az başa düşməyi təklif edirəm.

Sinif yükləyicisi

O, tərtib edilmiş bayt kodunu JVM-ə çatdırmaq üçün istifadə olunur, adətən uzantısı olan fayllarda saxlanılır .class, lakin digər mənbələrdən də əldə edilə bilər, məsələn, şəbəkə üzərindən yüklənmiş və ya proqramın özü tərəfindən yaradıla bilər. JVM-də siniflər necə yüklənir - 1Java SE spesifikasiyasına uyğun olaraq, JVM-də kodu işə salmaq üçün üç addımı tamamlamalısınız:
  • resurslardan bayt kodunu yükləmək və sinfin nümunəsini yaratmaqClass

    Buraya əvvəllər yüklənmişlər arasında tələb olunan sinfin axtarışı, yükləmək üçün bayt kodunun əldə edilməsi və onun düzgünlüyünün yoxlanılması, sinfin nümunəsinin yaradılması Class(iş vaxtında onunla işləmək üçün) və ana siniflərin yüklənməsi daxildir. Əgər ana siniflər və interfeyslər yüklənməyibsə, o zaman sözügedən sinif yüklənməmiş hesab olunur.

  • bağlama (və ya bağlama)

    Spesifikasiyaya görə, bu mərhələ daha üç mərhələyə bölünür:

    • Doğrulama , alınan bayt kodunun düzgünlüyü yoxlanılır.
    • Hazırlıq , RAM-ın statik sahələr üçün ayrılması və onların standart dəyərlərlə işə salınması (bu halda, əgər varsa, açıq başlatma artıq başlanğıc mərhələsində baş verir).
    • Rezolyutsiya , növlərin, sahələrin və metodların simvolik əlaqələrinin həlli.
  • qəbul edilmiş obyektin işə salınması

    burada, əvvəlki bəndlərdən fərqli olaraq, nə baş verməli, hər şey aydın görünür. Bunun necə baş verdiyini anlamaq, əlbəttə ki, maraqlı olardı.

Bütün bu addımlar aşağıdakı tələblərlə ardıcıl olaraq həyata keçirilir:
  • Əlaqələndirmədən əvvəl sinif tam yüklənməlidir.
  • Sinif işə salınmazdan əvvəl tam sınaqdan keçirilməli və hazırlanmalıdır.
  • Bağlantının həlli xətaları, hətta əlaqələndirmə mərhələsində aşkar edilsə belə, proqramın icrası zamanı baş verir.
Bildiyiniz kimi, Java siniflərin tənbəl (və ya tənbəl) yüklənməsini həyata keçirir. Bu o deməkdir ki, yüklənmiş sinfin istinad sahələrinin siniflərinin yüklənməsi tətbiq onlara açıq istinadla qarşılaşmayana qədər yerinə yetirilməyəcək. Başqa sözlə, simvolik bağlantıların həlli isteğe bağlıdır və standart olaraq baş vermir. Bununla belə, JVM tətbiqi enerjili sinif yükləməsindən də istifadə edə bilər, yəni. bütün simvolik keçidlər dərhal nəzərə alınmalıdır. Məhz bu baxımdan sonuncu tələb tətbiq olunur. Həm də qeyd etmək lazımdır ki, simvolik bağlantıların həlli sinif yüklənməsinin heç bir mərhələsi ilə əlaqəli deyil. Ümumiyyətlə, bu mərhələlərin hər biri yaxşı bir araşdırmaya səbəb olur; gəlin birincisini, yəni bayt kodunu yükləməyi anlamağa çalışaq.

Java yükləyicilərinin növləri

Java-da üç standart yükləyici var, onların hər biri müəyyən bir yerdən bir sinif yükləyir:
  1. Bootstrap , Primordial ClassLoader adlanan əsas yükləyicidir.

    rt.jar arxivindən standart JDK siniflərini yükləyir

  2. Extension ClassLoader – genişləndirici yükləyici.

    defolt olaraq jre/lib/ext qovluğunda yerləşən, lakin java.ext.dirs sistem xassəsi ilə təyin edilə bilən genişləndirmə siniflərini yükləyir.

  3. System ClassLoader – sistem yükləyicisi.

    CLASSPATH mühit dəyişənində müəyyən edilmiş tətbiq siniflərini yükləyir

Java sinif yükləyicilərinin iyerarxiyasından istifadə edir, burada kök, əlbəttə ki, əsasdır. Sonra genişləndirici yükləyici, sonra isə sistem yükləyicisi gəlir. Təbii ki, hər bir yükləyici özü bunu edə bilmədiyi halda yükləməni ona həvalə etmək üçün valideynə bir göstərici saxlayır.

Abstrakt sinif ClassLoader

Əsas yükləyici istisna olmaqla, hər bir yükləyici mücərrəd sinifin nəslindəndir java.lang.ClassLoader. Məsələn, genişləndirici yükləyicinin tətbiqi sinifdir sun.misc.Launcher$ExtClassLoader, sistem yükləyicisi isə sun.misc.Launcher$AppClassLoader. Əsas yükləyici yerlidir və onun tətbiqi JVM-ə daxildir. Genişlənən hər hansı bir sinif, java.lang.ClassLoaderblackjack və eyni olanlarla dərsləri yükləmək üçün öz yolunu təmin edə bilər. Bunun üçün müvafiq metodları yenidən müəyyən etmək lazımdır, bu anda mən yalnız səthi hesab edə bilərəm, çünki Bu məsələni ətraflı başa düşmədim. Budur onlar:
package java.lang;
public abstract class ClassLoader {
    public Class<?> loadClass(String name);
    protected Class<?> loadClass(String name, boolean resolve);
    protected final Class<?> findLoadedClass(String name);
    public final ClassLoader getParent();
    protected Class<?> findClass(String name);
    protected final void resolveClass(Class<?> c);
}
loadClass(String name)dərsləri yükləmək üçün giriş nöqtəsi olan bir neçə ictimai metoddan biridir. loadClass(String name, boolean resolve)Onun həyata keçirilməsi , ləğv edilməli olan başqa qorunan metodun çağırılması ilə nəticələnir . Bu qorunan metodun Javadoc-a baxsanız, aşağıdakı kimi bir şey başa düşə bilərsiniz: iki parametr giriş kimi verilir. Bunlardan biri yüklənməli olan sinfin binar adıdır (və ya tam uyğunlaşdırılmış sinif adı). Sinif adı bütün paketlərin siyahısı ilə müəyyən edilir. İkinci parametr simvolik keçid həllinin tələb olunub-olunmamasını müəyyən edən bayraqdır. Varsayılan olaraq false , yəni tənbəl sinif yükləməsindən istifadə olunur. Bundan əlavə, sənədlərə görə, metodun standart tətbiqində, findLoadedClass(String name)sinfin əvvəllər yüklənib-yüklənilmədiyini yoxlayan və əgər varsa, bu sinfə istinad qaytaran bir zəng edilir. Əks halda, ana yükləyicinin sinif yükləmə metodu çağırılacaq. Əgər yükləyicilərdən heç biri yüklənmiş sinfi tapa bilməsə, onların hər biri tərs ardıcıllıqla izləyərək, findClass(String name). Bu, “Sinif yükləmə sxemi” fəslində daha ətraflı müzakirə olunacaq. Və nəhayət, sonuncu, lakin ən azı, sinif yükləndikdən sonra, həll bayrağından asılı olaraq , simvolik keçidlər vasitəsilə siniflərin yüklənib-yüklənməyəcəyinə qərar veriləcək. Aydın bir nümunə, Rezolyutsiya mərhələsini sinif yükləmə mərhələsində çağırmaq olar. Müvafiq olaraq, sinfi genişləndirməklə ClassLoadervə onun üsullarını ləğv etməklə, fərdi yükləyici virtual maşına bayt kodu çatdırmaq üçün öz məntiqini həyata keçirə bilər. Java həmçinin "cari" sinif yükləyicisi konsepsiyasını dəstəkləyir. Cari yükləyici hazırda icra olunan sinfi yükləyəndir. Hər bir sinif hansı yükləyici ilə yükləndiyini bilir və siz bu məlumatı onun nömrəsinə zəng etməklə əldə edə bilərsiniz String.class.getClassLoader(). Bütün tətbiq sinifləri üçün "cari" yükləyici adətən sistemdir.

Sinif yüklənməsinin üç prinsipi

  • Nümayəndə heyəti

    Sinfin yüklənməsi sorğusu ana yükləyiciyə ötürülür və sinfin özünü yükləmək cəhdi yalnız ana yükləyici sinfi tapıb yükləyə bilmədikdə edilir. Bu yanaşma sinifləri bazaya mümkün qədər yaxın olan yükləyici ilə yükləməyə imkan verir. Bu, maksimum sinif görmə qabiliyyətinə nail olur. Hər bir yükləyici onun yüklədiyi siniflərin qeydini saxlayır və onları öz keşinə yerləşdirir. Bu siniflərin çoxluğuna əhatə dairəsi deyilir.

  • Görünüş

    Yükləyici yalnız "öz" siniflərini və "valideyn"in siniflərini görür və "uşaq" tərəfindən yüklənmiş siniflər haqqında heç bir fikri yoxdur.

  • Unikallıq

    Bir sinif yalnız bir dəfə yüklənə bilər. Nümayəndə heyəti mexanizmi sinif yükləməsini başlatan yükləyicinin əvvəllər JVM-ə yüklənmiş sinfi həddindən artıq yükləmədiyinə əmin olur.

Beləliklə, yükləyicisini yazarkən tərtibatçı bu üç prinsipi rəhbər tutmalıdır.

Sinif yükləmə sxemi

Bir sinfi yükləmək üçün zəng baş verdikdə, bu sinif cari yükləyicinin artıq yüklənmiş siniflərinin keşində axtarılır. İstədiyiniz sinif əvvəllər yüklənməyibsə, delegasiya prinsipi nəzarəti iyerarxiyada bir səviyyə yuxarıda yerləşən ana yükləyiciyə ötürür. Ana yükləyici də öz keşində istədiyiniz sinfi tapmağa çalışır. Əgər sinif artıq yüklənibsə və yükləyici onun yerini bilirsə, o zaman Classhəmin sinfin obyekti qaytarılacaq. Əks halda, axtarış əsas yükləyiciyə çatana qədər davam edəcək. Baza yükləyicinin tələb olunan sinif haqqında məlumatı yoxdursa (yəni hələ yüklənməyib), bu sinfin bayt kodu verilmiş yükləyicinin bildiyi siniflərin yerində axtarılacaq və əgər sinif bunu edə bilmirsə. yükləndikdə, idarəetmə ona məlum olan mənbələrdən yükləməyə çalışacaq uşaq yükləyiciyə qayıdacaq. Yuxarıda qeyd edildiyi kimi, əsas yükləyici üçün siniflərin yeri rt.jar kitabxanasıdır, genişləndirici yükləyici üçün - jre/lib/ext uzantıları olan kataloq, sistem üçün - CLASSPATH, istifadəçi üçün fərqli bir şey ola bilər. . Beləliklə, yükləmə siniflərinin tərəqqisi əks istiqamətdə - kök yükləyicidən cari birinə doğru gedir. Sinfin bayt kodu tapıldıqda, sinif JVM-ə yüklənir və növün nümunəsi əldə edilir Class. Asanlıqla gördüyünüz kimi, təsvir edilən yükləmə sxemi yuxarıda göstərilən metodun həyata keçirilməsinə bənzəyir loadClass(String name). Aşağıda bu diaqramı diaqramda görə bilərsiniz.
JVM-də siniflər necə yüklənir - 2

Nəticə olaraq

Dil öyrənməyin ilk addımlarında Java-da dərslərin necə yükləndiyini anlamağa xüsusi ehtiyac yoxdur, lakin bu əsas prinsipləri bilmək və ya kimi səhvlərlə qarşılaşdığınız zaman ümidsizliyə qapılmağınıza kömək ClassNotFoundExceptionedəcək NoClassDefFoundError. Yaxşı, ya da heç olmasa problemin kökünün nə olduğunu anlayın. ClassNotFoundExceptionBeləliklə, proqramın icrası zamanı sinif dinamik şəkildə yükləndikdə, yükləyicilər tələb olunan sinfi nə keşdə, nə də sinif yolu boyunca tapa bilmədikdə, istisna baş verir. Lakin səhv NoClassDefFoundErrordaha kritikdir və tələb olunan sinif tərtib zamanı mövcud olduqda, lakin proqramın icrası zamanı görünmədikdə baş verir. Bu, proqram istifadə etdiyi kitabxananı daxil etməyi unutduqda baş verə bilər. Yaxşı, işinizdə istifadə etdiyiniz alətin strukturunun prinsiplərini başa düşmək faktının özü (mütləq onun dərinliklərinə aydın və müfəssəl daldırma deyil) bu mexanizmin daxilində baş verən proseslərin başa düşülməsinə müəyyən aydınlıq əlavə edir. öz növbəsində, bu alətdən inamlı istifadəyə səbəb olur.

Mənbələr

ClassLoader Java-da necə işləyir Ümumiyyətlə, məlumatın əlçatan təqdimatı ilə çox faydalı mənbədir. Dərslərin yüklənməsi, ClassLoader Olduqca uzun məqalədir, lakin bu eyni olanlarla öz yükləyicinizi necə həyata keçirəcəyinizə diqqət yetirir. ClassLoader: siniflərin dinamik yüklənməsi Təəssüf ki, bu resurs hazırda mövcud deyil, lakin orada sinif yükləmə sxemi ilə ən başa düşülən diaqramı tapdım, ona görə də onu əlavə etməyə kömək edə bilmirəm. Java SE Spesifikasiyası: Fəsil 5. Yükləmə, Əlaqələndirmə və Başlama
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION