JavaRush /Java блогу /Random-KY /Класстар JVMге кантип жүктөлөт
Aleksandr Zimin
Деңгээл
Санкт-Петербург

Класстар JVMге кантип жүктөлөт

Группада жарыяланган
Программисттин ишинин эң татаал бөлүгү аяктагандан жана "Hello World 2.0" тиркемеси жазылгандан кийин, бөлүштүрүүчү комплектти чогултуп, кардарга же жок дегенде тестирлөө кызматына өткөрүп берүү гана калды. Бөлүштүрүүдө баары болушу керек, жана биз программабызды ишке киргизгенде, Java Virtual Machine сахнага чыгат. Жашыруун эмес, виртуалдык машина класстык файлдарда берилген буйруктарды byte code түрүндө окуйт жана аларды инструкция катары процессорго которот. Мен виртуалдык машинага кирүү byte-code схемасы жөнүндө бир аз түшүнүүнү сунуштайм.

Класс жүктөгүч

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

    буга суралган классты мурда жүктөлгөндөрдүн арасынан издөө, жүктөө үчүн byte codeду алуу жана анын тууралыгын текшерүү, класстын инстанциясын түзүү Class(иш учурунда аны менен иштөө үчүн) жана ата-энелер класстарын жүктөө кирет. Эгерде ата-эне класстары жана интерфейстери жүктөлө элек болсо, анда каралып жаткан класс жүктөлгөн жок деп эсептелет.

  • байланыштыруучу (же байланыштыруучу)

    спецификациясына ылайык, бул этап дагы үч этапка бөлүнөт:

    • Текшерүү , кабыл алынган byte codeдун тууралыгы текшерилет.
    • Даярдоо , статикалык талаалар үчүн оперативдүү эстутумду бөлүштүрүү жана аларды демейки маанилер менен инициализациялоо (бул учурда ачык инициализация, эгерде бар болсо, инициализация стадиясында ишке ашат).
    • Резолюция , типтердин, талаалардын жана методдордун символдук байланыштарынын чечorши.
  • алынган an objectти инициализациялоо

    Бул жерде, мурунку абзацтардан айырмаланып, баары эмне болушу керектиги ачык-айкын көрүнүп турат. Бул, албетте, бул кантип болуп жатканын так түшүнүү үчүн кызыктуу болмок.

Бардык бул кадамдар төмөнкү талаптар менен ырааттуу түрдө жүзөгө ашырылат:
  • Класс туташуудан мурун толугу менен жүктөлүшү керек.
  • Класс инициализацияланганга чейин толугу менен текшерorп, даярдалышы керек.
  • Шилтеменин чечorшиндеги каталар, алар шилтеме стадиясында аныкталган болсо да, программаны аткаруу учурунда пайда болот.
Белгилүү болгондой, Java класстарды жалкоо (же жалкоо) жүктөөнү ишке ашырат. Бул жүктөлгөн класстын шилтеме талааларынын класстарын жүктөө тиркеме аларга ачык шилтемеге туш болмоюнча аткарылbyte дегенди билдирет. Башка сөз менен айтканда, символдук шилтемелерди чечүү милдеттүү эмес жана демейки боюнча пайда болбойт. Бирок, JVM ишке ашыруу энергетикалык класс жүктөөсүн да колдоно алат, б.а. бардык символикалык шилтемелер дароо эске алынууга тийиш. Бул үчүн акыркы талап колдонулат. Ошондой эле белгилей кетүүчү нерсе, символдук шилтемелердин чечorши классты жүктөөнүн эч бир этабына байланbyte. Жалпысынан алганда, бул этаптардын ар бири жакшы изилдөөнү түзөт; келгиле, биринчисин аныктоого аракет кылалы, тактап айтканда 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. Негизги жүктөгүч жергorктүү жана аны ишке ашыруу 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 , бул жалкоо классты жүктөө колдонулат дегенди билдирет. Андан ары, documentацияга ылайык, методду демейки ишке ашырууда findLoadedClass(String name)класс мурда жүктөлгөн-жүктөлбөгөнүн текшерген чалуу жасалат жана эгер ошондой болсо, бул класска шилтемени кайтарат. Болбосо, аталык жүктөөчүнүн классты жүктөө ыкмасы чакырылат. Эгерде жүктөөчүлөрдүн эч кимиси жүктөлгөн классты таба албаса, алардын ар бири тескери тартипте, ошол классты таап, жүктөөгө аракет кылып findClass(String name), . Бул "Класс жүктөө схемасы" бөлүмүндө кененирээк талкууланат. Акыр-аягы, эң акыркысы, класс жүктөлгөндөн кийин, чечүүчү желекчеге жараша , класстарды символдук шилтемелер аркылуу жүктөө керекпи же жокпу, чечилет. Ачык мисал, Resolution стадиясын класс жүктөө стадиясында чакырса болот. Демек, классты кеңейтүү ClassLoaderжана анын ыкмаларын жокко чыгаруу менен, жеке жүктөгүч виртуалдык машинага byte codeду жеткирүү үчүн өзүнүн логикасын ишке ашыра алат. Java ошондой эле "учурдагы" класс жүктөгүчүнүн түшүнүгүн колдойт. Учурдагы жүктөгүч - учурда аткарылып жаткан классты жүктөгөн. Ар бир класс кайсы жүктөгүч менен жүктөлгөнүн билет жана бул маалыматты анын String.class.getClassLoader(). Колдонмолордун бардык класстары үчүн "учурдагы" жүктөгүч, адатта, система болуп саналат.

Классты жүктөөнүн үч принциби

  • Делегация

    Классты жүктөө өтүнүчү ата-эне жүктөгүчкө берилет жана класстын өзүн жүктөө аракети ата-энелик жүктөгүч классты таап, жүктөй албаса гана жасалат. Бул ыкма класстарды базага мүмкүн болушунча жакын жүктөгүч менен жүктөөгө мүмкүндүк берет. Бул максималдуу класстын көрүнүшүн камсыз кылат. Ар бир жүктөгүч өзү жүктөгөн класстардын эсебин сактап, аларды кэшине жайгаштырат. Бул класстардын жыйындысы масштаб деп аталат.

  • Көрүнүү

    Жүктөгүч "өзүнүн" класстарын жана "ата-энесинин" класстарын гана көрөт жана анын "баласы" жүктөгөн класстар жөнүндө эч кандай түшүнүгү жок.

  • Уникалдуулук

    Класс бир гана жолу жүктөлүшү мүмкүн. Делегация механизми классты жүктөөнү баштаган жүктөгүч JVMге мурда жүктөлгөн классты ашыкча жүктөбөшүнө ынанат.

Ошентип, жүктөгүчтү жазып жатканда, иштеп чыгуучу ушул үч принципти жетекчorкке алышы керек.

Классты жүктөө схемасы

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

Жыйынтык катары

Тил үйрөнүүнүн алгачкы кадамдарында класстар Javaда кантип жүктөлөрүн түшүнүүнүн өзгөчө кереги жок, бирок бул негизги принциптерди билүү же сыяктуу каталарга туш болгондо үмүтсүздүктөн качууга жардам ClassNotFoundExceptionберет NoClassDefFoundError. Мейли, же жок дегенде болжол менен маселенин тамыры эмнеде экенин түшүнүңүз. ClassNotFoundExceptionОшентип, программанын аткарылышы учурунда класс динамикалык түрдө жүктөлгөндө, жүктөөчүлөр керектүү классты кэштен же класс жолунда таба албай калганда, өзгөчө жагдай пайда болот. Бирок ката NoClassDefFoundErrorолуттуураак жана талап кылынган класс компиляция учурунда жеткorктүү болуп, бирок программаны аткаруу учурунда көрүнбөй калганда пайда болот. Бул программа өзү колдонгон китепкананы кошууну унутуп калса, болушу мүмкүн. Ооба, сиз өзүңүздүн ишиңизде колдонгон аспаптын түзүлүшүнүн принциптерин түшүнүү фактысынын өзү (анын тереңдигине так жана деталдуу чөмүлүү шарт эмес) бул механизмдин ичинде болуп жаткан процесстерди түшүнүүгө кандайдыр бир айкындык кошот. бул куралды ишенимдүү колдонууга алып келет.

Булактар

ClassLoader Java'да кандай иштейт Жалпысынан алганда, маалыматтын жеткorктүү презентациясы менен абдан пайдалуу булак. Класстарды жүктөө, ClassLoader Бул абдан узун макала, бирок ошол эле класстар менен өзүңүздүн жүктөгүчүңүздү кантип ишке ашырууга басым жасоо менен. ClassLoader: класстарды динамикалык жүктөө Тилекке каршы, бул ресурс азыр жеткorктүү эмес, бирок мен классты жүктөө схемасы менен эң түшүнүктүү диаграмманы таптым, ошондуктан мен аны кошпой коё албайм. Java SE спецификациясы: 5-бөлүм. Жүктөө, байланыштыруу жана баштоо
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION