JavaRush /Java blogi /Random-UZ /JVM ga sinflar qanday yuklanadi
Aleksandr Zimin
Daraja
Санкт-Петербург

JVM ga sinflar qanday yuklanadi

Guruhda nashr etilgan
Dasturchi ishining eng qiyin qismi tugallangandan va "Salom Dunyo 2.0" ilovasi yozilgandan so'ng, faqat tarqatish to'plamini yig'ish va uni mijozga yoki hech bo'lmaganda test xizmatiga o'tkazish qoladi. Tarqatishda hamma narsa xuddi shunday bo'ladi va biz dasturimizni ishga tushirganimizda, Java virtual mashinasi sahnaga chiqadi. Hech kimga sir emaski, virtual mashina sinf fayllarida bayt-kod ko'rinishida taqdim etilgan buyruqlarni o'qiydi va ularni protsessorga ko'rsatmalar sifatida tarjima qiladi. Men virtual mashinaga bayt-kodni kiritish sxemasi haqida bir oz tushunishni taklif qilaman.

Sinf yuklagichi

U JVM ga kompilyatsiya qilingan bayt kodini etkazib berish uchun ishlatiladi, u odatda kengaytmali fayllarda saqlanadi .class, lekin boshqa manbalardan ham olinishi mumkin, masalan, tarmoq orqali yuklab olingan yoki dasturning o'zi tomonidan yaratilgan. JVM-ga sinflar qanday yuklanadi - 1Java SE spetsifikatsiyasiga ko'ra, JVM-da ishlaydigan kodni olish uchun siz uchta bosqichni bajarishingiz kerak:
  • resurslardan bayt kodini yuklash va sinfning namunasini yaratishClass

    Bunga avvalroq yuklanganlar orasida soʻralgan sinfni qidirish, yuklash uchun bayt-kodni olish va uning toʻgʻriligini tekshirish, sinf namunasini yaratish Class(ish vaqtida u bilan ishlash uchun) va ota-sinflarni yuklash kiradi. Agar ota-sinflar va interfeyslar yuklanmagan bo'lsa, ko'rib chiqilayotgan sinf yuklanmagan deb hisoblanadi.

  • bog'lash (yoki bog'lash)

    Spetsifikatsiyaga ko'ra, bu bosqich yana uchta bosqichga bo'lingan:

    • Tekshirish , qabul qilingan bayt kodining to'g'riligi tekshiriladi.
    • Tayyorlash , statik maydonlar uchun RAMni ajratish va ularni standart qiymatlar bilan ishga tushirish (bu holda, agar mavjud bo'lsa, aniq ishga tushirish allaqachon ishga tushirish bosqichida sodir bo'ladi).
    • Rezolyutsiya , turlar, maydonlar va usullarning ramziy bog'lanishlarini hal qilish.
  • qabul qilingan ob'ektni ishga tushirish

    bu erda, oldingi paragraflardan farqli o'laroq, hamma narsa nima bo'lishi kerakligi aniq ko'rinadi. Albatta, bu qanday sodir bo'lishini tushunish qiziq.

Ushbu bosqichlarning barchasi quyidagi talablar bilan ketma-ket amalga oshiriladi:
  • Ulanishdan oldin sinf toʻliq yuklangan boʻlishi kerak.
  • Sinf to'liq sinovdan o'tkazilishi va ishga tushirilishidan oldin tayyorlanishi kerak.
  • Bog'lanishni aniqlashda xatoliklar, hatto ulanish bosqichida aniqlangan bo'lsa ham, dasturni bajarish paytida yuzaga keladi.
Ma'lumki, Java sinflarni dangasa (yoki dangasa) yuklashni amalga oshiradi. Bu shuni anglatadiki, yuklangan sinfning mos yozuvlar maydonlari sinflarini yuklash dastur ularga aniq havolaga duch kelmaguncha bajarilmaydi. Boshqacha qilib aytganda, ramziy havolalarni hal qilish ixtiyoriy va sukut bo'yicha sodir bo'lmaydi. Shu bilan birga, JVMni amalga oshirish energetik sinf yuklashdan ham foydalanishi mumkin, ya'ni. barcha ramziy havolalar darhol hisobga olinishi kerak. Aynan shu nuqta uchun oxirgi talab qo'llaniladi. Shuni ham ta'kidlash kerakki, ramziy havolalarning o'lchamlari sinfni yuklashning hech qanday bosqichiga bog'liq emas. Umuman olganda, ushbu bosqichlarning har biri yaxshi o'rganishga imkon beradi; keling, birinchisini aniqlashga harakat qilaylik, ya'ni bayt kodini yuklaymiz.

Java yuklagichlarining turlari

Java-da uchta standart yuklagich mavjud bo'lib, ularning har biri ma'lum bir joydan sinfni yuklaydi:
  1. Bootstrap - bu asosiy yuklovchi bo'lib, u Primordial ClassLoader deb ham ataladi.

    rt.jar arxividan standart JDK sinflarini yuklaydi

  2. Extension ClassLoader - kengaytmali yuklovchi.

    sukut bo'yicha jre/lib/ext katalogida joylashgan kengaytma sinflarini yuklaydi, lekin java.ext.dirs tizim xususiyati tomonidan o'rnatilishi mumkin.

  3. System ClassLoader - tizim yuklagichi.

    CLASSPATH muhit o'zgaruvchisida belgilangan dastur sinflarini yuklaydi

Java sinf yuklagichlarining ierarxiyasidan foydalanadi, bu erda ildiz, albatta, asosiy hisoblanadi. Keyinchalik kengaytma yuklagichi, so'ngra tizim yuklagichi keladi. Tabiiyki, har bir yuklovchi, agar o'zi buni qila olmasa, yuklashni unga topshirish imkoniyatiga ega bo'lish uchun ota-onaga ko'rsatgichni saqlaydi.

Abstrakt sinf ClassLoader

Har bir yuklovchi, asosiysidan tashqari, mavhum sinfning avlodidir java.lang.ClassLoader. Masalan, kengaytmali yuklovchining amalga oshirilishi sinf sun.misc.Launcher$ExtClassLoader, tizim yuklagichi esa sun.misc.Launcher$AppClassLoader. Asosiy yuklovchi mahalliy bo'lib, uni amalga oshirish JVMga kiritilgan. Kengaytirilgan har qanday sinf java.lang.ClassLoaderblackjack va shu kabilar bilan sinflarni yuklashning o'ziga xos usulini taqdim etishi mumkin. Buni amalga oshirish uchun tegishli usullarni qayta belgilash kerak, ularni hozirda faqat yuzaki ko'rib chiqish mumkin, chunki Men bu masalani batafsil tushunmadim. Mana ular:
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)sinflarni yuklash uchun kirish nuqtasi bo'lgan bir nechta ommaviy usullardan biri. Uni amalga oshirish boshqa himoyalangan usulni chaqirish bilan tugaydi loadClass(String name, boolean resolve), uni bekor qilish kerak. Agar siz ushbu himoyalangan usulning Javadoc-ga qarasangiz, quyidagi kabi narsalarni tushunishingiz mumkin: ikkita parametr kirish sifatida taqdim etiladi. Ulardan biri yuklanishi kerak bo'lgan sinfning ikkilik nomi (yoki to'liq malakali sinf nomi). Sinf nomi barcha paketlar ro'yxati bilan ko'rsatilgan. Ikkinchi parametr - ramziy havola o'lchamlari zarurligini aniqlaydigan bayroq. Odatiy bo'lib , u noto'g'ri , ya'ni dangasa sinf yuklash ishlatiladi. Bundan tashqari, hujjatlarga ko'ra, usulning sukut bo'yicha amalga oshirilishida qo'ng'iroq qilinadi findLoadedClass(String name), u sinf allaqachon yuklangan yoki yo'qligini tekshiradi va agar shunday bo'lsa, ushbu sinfga havolani qaytaradi. Aks holda, asosiy yuklovchining sinf yuklash usuli chaqiriladi. Agar yuklovchilarning hech biri yuklangan sinfni topa olmasa, ularning har biri teskari tartibda kuzatib, findClass(String name). Bu "Sinflarni yuklash sxemasi" bobida batafsilroq muhokama qilinadi. Va nihoyat, oxirgi, lekin eng muhimi, sinf yuklangandan so'ng, hal qilish bayrog'iga qarab , sinflarni ramziy havolalar orqali yuklash to'g'risida qaror qabul qilinadi. Aniq misol, Rezolyutsiya bosqichini sinfni yuklash bosqichida chaqirish mumkin. Shunga ko'ra, sinfni kengaytirish ClassLoaderva uning usullarini bekor qilish orqali maxsus yuklovchi virtual mashinaga bayt kodini etkazib berish uchun o'z mantiqini amalga oshirishi mumkin. Java shuningdek, "joriy" sinf yuklagichi tushunchasini qo'llab-quvvatlaydi. Joriy yuklovchi hozirda bajarilayotgan sinfni yuklagan. Har bir sinf qaysi yuklagich bilan yuklanganligini biladi va siz bu ma'lumotni uning ga qo'ng'iroq qilib olishingiz mumkin String.class.getClassLoader(). Barcha dastur sinflari uchun "joriy" yuklovchi odatda tizim hisoblanadi.

Sinflarni yuklashning uchta printsipi

  • Delegatsiya

    Sinfni yuklash so'rovi asosiy yuklovchiga uzatiladi va sinfni o'zi yuklashga urinish faqat ota-ona yuklovchi sinfni topa olmasa va yuklay olmasa amalga oshiriladi. Ushbu yondashuv sizga sinflarni asosiyga imkon qadar yaqin bo'lgan yuklagich bilan yuklash imkonini beradi. Bu sinfning maksimal ko'rinishiga erishadi. Har bir yuklovchi o'zi tomonidan yuklangan sinflarni qayd qilib, ularni keshga joylashtiradi. Ushbu sinflar to'plami qamrov deb ataladi.

  • Ko'rinish

    Yuklovchi faqat "o'z" sinflarini va "ota-ona" ning sinflarini ko'radi va uning "bola" tomonidan yuklangan sinflar haqida hech qanday tasavvurga ega emas.

  • O'ziga xoslik

    Sinf faqat bir marta yuklanishi mumkin. Delegatsiya mexanizmi sinfni yuklashni boshlagan yuklovchi JVM ga avval yuklangan sinfni ortiqcha yuklamasligiga ishonch hosil qiladi.

Shunday qilib, bootloaderni yozishda ishlab chiquvchi ushbu uchta tamoyilga amal qilishi kerak.

Sinfni yuklash sxemasi

Sinfni yuklash uchun qo'ng'iroq sodir bo'lganda, bu sinf joriy yuklovchining allaqachon yuklangan sinflari keshida qidiriladi. Agar kerakli sinf ilgari yuklanmagan bo'lsa, delegatsiya printsipi boshqaruvni ierarxiyada bir daraja yuqoriroq joylashgan ota-loaderga o'tkazadi. Ota yuklovchi ham keshda kerakli sinfni topishga harakat qiladi. Agar sinf allaqachon yuklangan bo'lsa va yuklovchi uning joylashgan joyini bilsa, u holda Classushbu sinf ob'ekti qaytariladi. Aks holda, qidiruv asosiy yuklash moslamasiga yetguncha davom etadi. Agar asosiy yuklovchida kerakli sinf haqida ma'lumot bo'lmasa (ya'ni u hali yuklanmagan bo'lsa), bu sinfning bayt kodi yuklovchi biladigan sinflar joylashgan joyda qidiriladi va agar sinf bo'lmasa. yuklangan boʻlsa, boshqaruv unga maʼlum boʻlgan manbalardan yuklashga urinib koʻradigan bola yuklagichga qaytadi. Yuqorida aytib o'tilganidek, asosiy yuklovchi uchun sinflarning joylashuvi rt.jar kutubxonasi, kengaytmali yuklovchi uchun - jre/lib/ext kengaytmalari bo'lgan katalog, tizim uchun - CLASSPATH, foydalanuvchi uchun u boshqacha bo'lishi mumkin. . Shunday qilib, yuklash sinflarining rivojlanishi teskari yo'nalishda - ildiz yuklagichdan joriygacha boradi. Sinfning bayt-kodi topilganda, sinf JVM ga yuklanadi va turning namunasi olinadi Class. Osonlik bilan ko'rib turganingizdek, tasvirlangan yuklash sxemasi yuqoridagi usulni amalga oshirishga o'xshaydi loadClass(String name). Quyida ushbu diagrammani diagrammada ko'rishingiz mumkin.
JVM-ga sinflar qanday yuklanadi - 2

Xulosa sifatida

Tilni o'rganishning dastlabki bosqichlarida Java-da sinflar qanday yuklanishini tushunishning alohida ehtiyoji yo'q, ammo bu asosiy tamoyillarni bilish yoki kabi xatolarga duch kelganingizda umidsizlikdan qochishingizga yordam ClassNotFoundExceptionberadi NoClassDefFoundError. Xo'sh, yoki hech bo'lmaganda muammoning ildizi nima ekanligini tushunib oling. ClassNotFoundExceptionShunday qilib, dasturni bajarish jarayonida sinf dinamik yuklanganda, yuklovchilar keshda ham, sinf yo'li bo'ylab ham kerakli sinfni topa olmasa, istisno yuzaga keladi. Ammo xato NoClassDefFoundErroryanada jiddiyroq va kerakli sinf kompilyatsiya paytida mavjud bo'lganda paydo bo'ladi, lekin dasturni bajarish paytida ko'rinmaydi. Agar dastur o'zi foydalanadigan kutubxonani qo'shishni unutgan bo'lsa, bu sodir bo'lishi mumkin. Xo'sh, o'z ishingizda foydalanadigan asbobning tuzilishi tamoyillarini tushunish haqiqati (uning chuqurligiga aniq va batafsil botirish shart emas) ushbu mexanizm ichida sodir bo'layotgan jarayonlarni tushunishga aniqlik kiritadi. o'z navbatida, ushbu vositadan ishonchli foydalanishga olib keladi.

Manbalar

ClassLoader Java'da qanday ishlaydi Umuman olganda, ma'lumotlarning mavjud taqdimoti bilan juda foydali manba. Sinflarni yuklash, ClassLoader Juda uzun maqola, lekin aynan shular bilan o'z yuklagichingizni qanday amalga oshirishga urg'u berilgan. ClassLoader: sinflarni dinamik yuklash Afsuski, bu resurs hozir mavjud emas, lekin u erda men sinfni yuklash sxemasi bilan eng tushunarli diagrammani topdim, shuning uchun uni qo'shishdan boshqa ilojim yo'q. Java SE spetsifikatsiyasi: 5-bob. Yuklash, ulash va ishga tushirish
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION