JavaRush /Java блогы /Random-KK /JVM жүйесіне сыныптар қалай жүктеледі
Aleksandr Zimin
Деңгей
Санкт-Петербург

JVM жүйесіне сыныптар қалай жүктеледі

Топта жарияланған
Бағдарламашы жұмысының ең қиын бөлігі аяқталғаннан кейін және «Hello World 2.0» қосымшасы жазылғаннан кейін, тарату жинағын жинап, оны тұтынушыға немесе кем дегенде тестілеу қызметіне беру ғана қалады. Дистрибьюцияда бәрі болуы керек, және біз бағдарламаны іске қосқан кезде Java виртуалды машинасы сахнаға шығады. Жасыратыны жоқ, виртуалды машина класс файлдарында byte code түрінде берілген командаларды оқиды және оларды процессорға нұсқаулар ретінде аударады. Мен виртуалды машинаға byte-codeты енгізу схемасы туралы аздап түсінуді ұсынамын.

Сынып жүктегіш

Ол JVM-ге компиляцияланған byte-codeты жеткізу үшін пайдаланылады, ол әдетте кеңейтімі бар файлдарда сақталады .class, бірақ оны басқа көздерден алуға болады, мысалы, желі арқылы жүктеледі немесе қолданбаның өзі жасайды. JVM жүйесінде сыныптар қалай жүктеледі - 1Java SE спецификациясына сәйкес, JVM жүйесінде іске қосылған codeты алу үшін сізге үш қадамды орындау қажет:
  • ресурстардан byte-codeты жүктеу және сынып данасын жасауClass

    бұған бұрын жүктелгендердің арасынан сұралған сыныпты іздеу, жүктеу үшін byte codeты алу және оның дұрыстығын тексеру, сынып данасын жасау Class(орындалу уақытында онымен жұмыс істеу үшін) және ата-аналық сыныптарды жүктеу кіреді. Егер ата-аналық сыныптар мен интерфейстер жүктелмеген болса, онда қарастырылып отырған сынып жүктелмеген болып саналады.

  • байланыстыру (немесе байланыстыру)

    Спецификацияға сәйкес бұл кезең тағы үш кезеңге бөлінеді:

    • Тексеру , алынған byte-codeтың дұрыстығы тексеріледі.
    • Дайындық , статикалық өрістер үшін жедел жадты бөлу және оларды әдепкі мәндермен инициализациялау (бұл жағдайда анық инициализация, егер бар болса, инициализация сатысында орын алады).
    • Резолюция , түрлердің, өрістердің және әдістердің символдық байланыстарын шешу.
  • алынған нысанды инициализациялау

    мұнда, алдыңғы абзацтардан айырмашылығы, бәрі не болуы керек екені түсінікті сияқты. Мұның қалай болатынын түсіну, әрине, қызықты болар еді.

Барлық осы қадамдар келесі талаптармен дәйекті түрде орындалады:
  • Байланыстыру алдында сынып толығымен жүктелуі керек.
  • Сынып инициализациядан бұрын толық тексеріліп, дайындалуы керек.
  • Сілтеме ажыратымдылығының қателері, егер олар байланыстыру кезеңінде анықталған болса да, бағдарламаны орындау кезінде орын алады.
Өздеріңіз білетіндей, Java сабақтарды жалқау (немесе жалқау) жүктеуді жүзеге асырады. Бұл жүктелген сыныптың анықтамалық өрістерінің сыныптарын жүктеу қолданба оларға нақты сілтеме таппайынша орындалмайтынын білдіреді. Басқаша айтқанда, символдық сілтемелерді шешу міндетті емес және әдепкі бойынша орындалмайды. Дегенмен, JVM іске асыру энергетикалық сыныпты жүктеуді де пайдалана алады, яғни. барлық символдық сілтемелер дереу ескерілуі керек. Дәл осы сәтте соңғы талап қолданылады. Сондай-ақ, символдық сілтемелердің рұқсаты сыныпты жүктеудің кез келген кезеңіне байланысты емес екенін атап өткен жөн. Жалпы алғанда, осы кезеңдердің әрқайсысы жақсы зерттеуге мүмкіндік береді; біріншісін анықтауға тырысайық, атап айтқанда byte codeты жүктеу.

Java жүктегіштерінің түрлері

Java-да үш стандартты жүктеуші бар, олардың әрқайсысы белгілі бір жерден сыныпты жүктейді:
  1. Bootstrap - негізгі жүктеуші, оны Primordial ClassLoader деп те атайды.

    rt.jar мұрағатынан стандартты JDK сыныптарын жүктейді

  2. Extension ClassLoader – кеңейтім жүктеушісі.

    әдепкі бойынша jre/lib/ext каталогында орналасқан кеңейтім сыныптарын жүктейді, бірақ java.ext.dirs жүйе сипаты арқылы орнатылуы мүмкін.

  3. System ClassLoader – жүйелік жүктеуші.

    CLASSPATH ортасының айнымалы мәнінде анықталған қолданба сыныптарын жүктейді

Java класс жүктеушілер иерархиясын пайдаланады, мұнда түбір, әрине, негізгі болып табылады. Содан кейін кеңейтім жүктеушісі, содан кейін жүйелік жүктеуші келеді. Әрине, әрбір жүктеуші өзі мұны істей алмаған жағдайда оған жүктеуді тапсыра алу үшін ата-анаға көрсеткішті сақтайды.

ClassLoader дерексіз класс

Әрбір жүктеуші, негізгіден басқа, абстрактілі сыныптың ұрпағы болып табылады java.lang.ClassLoader. Мысалы, кеңейтім жүктегішінің іске асырылуы - класс sun.misc.Launcher$ExtClassLoader, ал жүйелік жүктеушісі - sun.misc.Launcher$AppClassLoader. Негізгі жүктеуші түпнұсқа болып табылады және оны іске асыру JVM құрамына кіреді. Кеңейтілген кез келген класс java.lang.ClassLoaderблэкджекпен және сол сияқты класстарды жүктеудің өзіндік әдісін қамтамасыз ете алады. Ол үшін сәйкес әдістерді қайта анықтау керек, оларды қазіргі уақытта тек үстірт қарастыруға болады, өйткені Мен бұл мәселені егжей-тегжейлі түсінбедім. Міне олар:
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)сыныптарды жүктеуге арналған кіру нүктесі болып табылатын бірнеше жалпы әдістердің бірі. Оның орындалуы басқа қорғалған әдісті шақыруға дейін төмендейді loadClass(String name, boolean resolve), оны қайта анықтау қажет. Осы қорғалған әдістің Javadoc нұсқасын қарасаңыз, келесідей нәрсені түсінуге болады: екі параметр енгізу ретінде беріледі. Біреуі жүктелуі қажет сыныптың екілік атауы (немесе толық жарамды сынып атауы). Сынып атауы барлық бумалардың тізімімен көрсетіледі. Екінші параметр - символдық сілтеме ажыратымдылығы қажет екенін анықтайтын жалауша. Әдепкі бойынша ол false , яғни жалқау сыныпты жүктеу қолданылады. Әрі қарай, құжаттамаға сәйкес, әдісті әдепкі іске асыруда findLoadedClass(String name)сыныптың бұрын жүктелген-жүктелмегенін тексеретін шақыру жасалады және егер солай болса, осы сыныпқа сілтеме қайтарады. Әйтпесе, негізгі жүктеушінің классты жүктеу әдісі шақырылады. Жүктеушілердің ешқайсысы жүктелген сыныпты таба алмаса, олардың әрқайсысы кері ретпен орындап, findClass(String name). Бұл «Сыныптарды жүктеу схемасы» тарауында толығырақ қарастырылады. Соңында, ең бастысы, сынып жүктелгеннен кейін шешу жалаушасына байланысты , сыныптарды символдық сілтемелер арқылы жүктеу керек пе деген шешім қабылданады. Айқын мысал, Шешім кезеңін сыныпты жүктеу кезеңінде шақыруға болады. Тиісінше, сыныпты кеңейту ClassLoaderжәне оның әдістерін қайта анықтау арқылы теңшелетін жүктеуші виртуалды машинаға byte codeты жеткізу үшін өз логикасын жүзеге асыра алады. Java сонымен қатар «ағымдағы» класс жүктеушісі тұжырымдамасын қолдайды. Ағымдағы жүктеуші - ағымдағы орындалатын сыныпты жүктеген. Әрбір сынып қай жүктегішпен жүктелгенін біледі және сіз бұл ақпаратты оның String.class.getClassLoader(). Қолданбалардың барлық сыныптары үшін «ағымдағы» жүктеуші әдетте жүйелік болып табылады.

Классты жүктеудің үш принципі

  • Делегация

    Классты жүктеу сұрауы ата-аналық жүктеушіге жіберіледі және сыныпты жүктеу әрекеті тек ата-аналық жүктеуші сыныпты тауып, жүктей алмаған жағдайда ғана жасалады. Бұл тәсіл сыныптарды негізгіге мүмкіндігінше жақын жүктегішпен жүктеуге мүмкіндік береді. Бұл сыныптың максималды көрінуіне қол жеткізеді. Әрбір жүктеуші өзі жүктеген сыныптардың жазбасын сақтайды, оларды кэшке орналастырады. Бұл сыныптардың жиыны аумақ деп аталады.

  • Көріну

    Жүктеуші тек «өз» сыныптары мен «ата-ананың» сыныптарын көреді және оның «баласы» жүктеген сыныптар туралы түсінбейді.

  • Бірегейлік

    Класс тек бір рет жүктелуі мүмкін. Делегация механизмі сыныпты жүктеуді бастайтын жүктеушінің JVM жүйесіне бұрын жүктелген сыныпты шамадан тыс жүктемеуін қамтамасыз етеді.

Осылайша, жүктеушісін жазған кезде әзірлеуші ​​осы үш принципті басшылыққа алуы керек.

Сыныптың жүктелу схемасы

Классты жүктеуге шақыру орын алған кезде, бұл сынып ағымдағы жүктеушінің бұрыннан жүктелген сыныптарының кэшінде ізделеді. Қажетті сынып бұрын жүктелмеген болса, өкілеттілік принципі басқаруды иерархияда бір деңгей жоғары орналасқан негізгі жүктеушіге береді. Ата-аналық жүктеуші де өзінің кэшінде қажетті классты табуға тырысады. Егер сынып әлдеқашан жүктелген болса және жүктеуші оның орнын білсе, онда Classсол сыныптың нысаны қайтарылады. Олай болмаса, іздеу негізгі жүктеушіге жеткенше жалғасады. Егер базалық жүктеушіде қажетті класс туралы ақпарат болмаса (яғни ол әлі жүктелмеген), бұл сыныптың byte codeы жүктеуші білетін сыныптар орналасқан жерден ізделеді, ал егер сынып мүмкін болмаса. жүктелген болса, басқару оған белгілі көздерден жүктеуге тырысатын еншілес жүктегішке қайта оралады. Жоғарыда айтылғандай, базалық жүктеуші үшін сыныптардың орны rt.jar кітапханасы, кеңейтім жүктеушісі үшін - jre/lib/ext кеңейтімдері бар каталог, бір жүйе үшін - CLASSPATH, пайдаланушы үшін ол басқаша болуы мүмкін. . Осылайша, жүктеу кластарының барысы қарама-қарсы бағытта жүреді - түбірлік жүктеушіден ағымдағыға дейін. Сыныптың byte codeы табылған кезде, сынып JVM-ге жүктеледі және түрдің данасы алынады Class. Көріп отырғаныңыздай, сипатталған жүктеу схемасы жоғарыда аталған әдісті іске асыруға ұқсас loadClass(String name). Төменде сіз бұл диаграмманы диаграммада көре аласыз.
JVM-де сыныптар қалай жүктеледі - 2

Қорытынды ретінде

ClassNotFoundExceptionТілді үйренудің алғашқы қадамдарында Java тілінде сыныптардың қалай жүктелетінін түсінудің ерекше қажеттілігі жоқ, бірақ осы негізгі принциптерді білу немесе сияқты қателерге тап болған кезде үмітсіздіктен аулақ болуға көмектеседі NoClassDefFoundError. Жақсы, немесе кем дегенде, мәселенің түбірі неде екенін түсініңіз. ClassNotFoundExceptionОсылайша, бағдарламаны орындау кезінде сынып динамикалық жүктелгенде, жүктеушілер кэште немесе сынып жолында қажетті класс таба алмаған кезде ерекше жағдай орын алады. Бірақ қате NoClassDefFoundErrorмаңыздырақ және қажетті сынып компиляция кезінде қол жетімді болған кезде пайда болады, бірақ бағдарламаны орындау кезінде көрінбейді. Бұл бағдарлама өзі пайдаланатын кітапхананы қосуды ұмытып кеткен жағдайда орын алуы мүмкін. Сіздің жұмысыңызда қолданатын құралдың құрылымының принциптерін түсіну фактісі (оның тереңдігіне анық және егжей-тегжейлі ену міндетті емес) осы механизмнің ішінде болып жатқан процестерді түсінуге біршама айқындық қосады. бұл құралды сенімді пайдалануға әкеледі.

Дереккөздер

ClassLoader Java-да қалай жұмыс істейді Жалпы ақпараттың қолжетімді көрсетілімі бар өте пайдалы дереккөз. Класстарды жүктеу, ClassLoader Өте ұзақ мақала, бірақ дәл осылармен өз жүктеушіні іске асыру жолына баса назар аударылады. ClassLoader: сыныптарды динамикалық жүктеу Өкінішке орай, бұл ресурс қазір қол жетімді емес, бірақ мен сыныпты жүктеу схемасы бар ең түсінікті диаграмманы таптым, сондықтан мен оны қосуға көмектесе алмаймын. Java SE спецификациясы: 5-тарау. Жүктеу, байланыстыру және инициализациялау
Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION