IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

2. diel - Classloader a prvý modul v Jave

V predchádzajúcej lekcii, Úvod do modulov v Jave , sme sa zoznámili so štruktúrou a vlastnosťami modulov a ukázali si, ako pomáhajú riešiť problematiku závislosti balíčkov.

V tejto lekcii budeme ešte chvíľku pokračovať v teórii. V dnešnom Java tutoriále si povieme, ako funguje classloader a zoznámime sa s rôznymi typmi modulov. Na záver si ukážeme, ako taký modul vyzerá.

Načítanie tried

O načítanie tried v aplikácii sa stará tzv. classloader. V Jave existujú celkom tri druhy classloaderov:

  • Bootstrap classloader - základný classloader, naimplementovaný priamo v C++ (nie v Jave), starajúci sa o načítanie kritických modulov, ako je java.base,
  • Platform classloader - tento classloader je zodpovedný za načítanie všetkých nekritických modulov, ktoré ale sú stále súčasťou JRE, ako je java.sql,
  • System (Application) classloader - posledný classloader načíta všetky ostatné moduly, typicky sa jedná o nami vytvorené moduly a všetky knižnice tretích strán.
Výpočet modulov, ktoré sa načítajú Bootstrap a Platform classloaderom je možné dohľadať v dotaze zo Stack Overflow.

Hierarchia týchto troch classloaderov je rovnaká, ako v našom zozname. Platform má ako svojho rodiča nastavený Bootstrap a sám je rodičom System (Application). Bootstrap žiadneho rodiča nemá.

Načítanie tried má jasne definované flow, ktoré môžeme vidieť na obrázku nižšie:

Proces načítania tried - Moduly v Jave

Poďme si jednotlivé kroky bližšie popísať:

  1. Na začiatku je požiadavka na načítanie triedy.
  2. Skontroluje sa, či sa už trieda niekedy v minulosti nenačítala, pokiaľ áno, vráti sa z cache (tento bod nie je v grafe).
  3. Najprv sa požiadavka dostane k System (Application) classloaderu, ktorý ho rovno deleguje na svojho rodiča - Platform classloader.
  4. Platform classloader opäť rovno deleguje požiadavku na svojho rodiča - Bootstrap classloader.
  5. Bootstrap classloader žiadneho rodiča nemá, takže sa pozrie, či je schopný požadovanú triedu načítať. Ak áno, triedu vráti. Ak nie, vráti sa vyhľadávanie triedy späť do Platform classloaderu.
  6. Platform classloader sa teraz už pozrie, či je schopný triedu načítať. Ak áno, triedu vráti. Ak nie, vráti vyhľadávanie triedy späť do System (Application) classloaderu.
  7. System (Application) classloader je posledný, kto môže triedu načítať. V prípade neúspechu sa vyhodí veľmi známa a nepríjemná výnimka ClassNotFoundException.
V ukážke nižšie uvidíte po spustení kódu, že rôzne triedy naozaj vracajú rôzne classloadery:
System.out.println(System.Logger.class.getClassLoader());
System.out.println(java.sql.SQLPermission.class.getClassLoader());
System.out.println(Program.class.getClassLoader());

Výstup:

Konzolová aplikácia
null
jdk.internal.loader.ClassLoaders$PlatformClassLoader@273f6b01
jdk.internal.loader.ClassLoaders$AppClassLoader@42110406

Classloadery hrajú dôležitú úlohu v kombinácii s modulmi. Keď už vieme, že existujú mechanizmy na načítanie tried, poďme si ešte v rýchlosti definovať pojem class shadowing.

Class shadowing

Class shadowing je nepríjemný následok spôsobu načítania tried v Jave 8 av predchádzajúcich verziách.

Majme dve knižnice, ktoré z nejakého dôvodu majú rovnaký názov balíčka a obsahujú aj rovnakú metódu. Takáto situácia typicky nastane v prípade, keď naša aplikácia využíva mnoho knižníc. Tieto knižnice majú tiež svoje závislosti, avšak ich závislosti už môžu mať staršiu verziu. Takže sa nakoniec stane, že knižnica bude na classpath viackrát.

V takom prípade je použitá trieda z knižnice, ktorá je na classpath nájdená ako prvá. Moduly by mali tomuto správaniu zabrániť, pretože musia mať unikátne názvy.

Kým budú používané knižnice, ktoré nie sú modularizované, bude vždy existovať riziko shadowingu.

Typy modulov

Moduly v Jave možno rozdeliť do štyroch kategórií: systémové, aplikačné, automatické a bezmenné.

Systémové moduly

Medzi systémové moduly patria všetky moduly z Java SE a zároveň moduly z JDK. Tieto moduly je možné používať bez žiadneho špeciálneho nastavovania a sú automaticky dostupné.

Aplikačné moduly

Všetky ostatné moduly, ktoré my ako programátori vytvoríme, sa radia medzi aplikačné moduly. Každý nami vytvorený modul musí mať v aplikácii, ktorú vyvíjame unikátny názov. Pokiaľ to nezaistíme, aplikáciu nepôjde skompilovať.

Automatické moduly

Knižnice, ktoré ešte neboli modularizované, môžu byť zaradené medzi automatické moduly, ak sa vložia na modulepath. Automatické moduly dostanú názov automaticky. Buď sa použije názov definovaný v manifeste pod hlavičkou Automatic-Module-Name, alebo sa názov automaticky odvodí z názvu JAR súboru, v ktorom sa automatický modul nachádza.

Automatické moduly automaticky exportujú všetky balíčky a povoľujú prístup cez reflexiu. Ďalej im je umožnené čítať verejné API ostatných modulov (vrátane pomenovaných).

Bezmenné moduly

Knižnice, ktoré ešte neboli modularizované, budú zaradené medzi bezmenné moduly, ak sa vložia na classpath.

Bezmenné moduly tiež automaticky exportujú všetky balíčky a povoľujú prístup cez reflexiu. Ďalej môžu čítať verejné API ostatných modulov dostupných na modulepath a všetky knižnice dostupné na classpath.

Na druhej strane nie je možné používať bezmenné moduly v pomenovaných moduloch.

Definícia modulu

Moduly sa definujú v špeciálnom súbore nazvanom module-info.java. Tento súbor nájdeme v src zložke daného modulu. V prípade Mavenu sa definícia modulu vkladá do zložky src/main/java.

Ako prvé je potrebné v súbore uviesť kľúčové slovo module nasledované názvom modulu. Modul si môžeme nazvať, ako potrebujeme. V prípade Javy, zvolili vývojári jednoduché pomenovanie java.nazov_modulu . Teda java.base, java.logging, java.xml atď. Knižnica JavaFX používa podobné pomenovanie: javafx.base, javafx.controls, javafx.fxml. Veľké množstvo knižníc ale používa ako názov modulu názov balíčkov, v ktorých sa knižnica nachádza. Napríklad JAXB knižnica má názov modulu jakarta.xml.bind.

Po názve modulu nasledujú zložené zátvorky. Prázdny modul, ktorý na ničom nezávisí a nič neexportuje, môže vyzerať napríklad takto:

module cz.itnetwork.moduly.prvnimodul {
  // zde se budou definovat veřejně dostupné moduly
  // a závislosti
}

Ďalej je vhodné dodržať menné konvencie projektu, modulov a výsledných artefaktov. Majme projekt nazvaný cz.itnetwork.moduly, ktorý je rozdelený na niekoľko samostatných modulov prvnimodul a druhymodul. Takýto projekt môže mať napríklad nasledujúcu štruktúru:

cz.itnetwork.moduly - kořenová složka celého projektu
|- cz.itnetwork.moduly.prvnimodul - první modul
|  |-src
|    |- module-info.java - module info prvního modulu
|    |- cz - balíčky prvního modulu
|        |- itnetwork
|          |- moduly
|             |- prvnimodul
|                |- TridaA.java - třída v prvním modulu
|- cz.itnetwork.moduly.druhymodul - druhý modul
   |-src
     |- module-info.java - module info druhého modulu
     |- cz - balíčky druhého modulu
        |- itnetwork
           |- moduly
              |- druhymodul
                 |- TridaB.java - třída ve druhém modulu

Artefakty môžeme pomenovať len po module prvnimodul, prípadne môžu obsahovať aj celý názov cz.itnetwork.moduly.prvnimodul. Všetko si ukážeme na praktických príkladoch, ktoré nás čakajú v ďalších lekciách.

V ďalšej lekcii, Vytvorenie prvého modulu v Jave , si po vzore prvých lekcií OOP vytvoríme projekt "Zdravíc" s tromi modulmi a ukážeme si, ako jednotlivé moduly konfigurovať, aby boli schopné medzi sebou komunikovať.


 

Predchádzajúci článok
Úvod do modulov v Jave
Všetky články v sekcii
Moduly v Jave
Preskočiť článok
(neodporúčame)
Vytvorenie prvého modulu v Jave
Článok pre vás napísal Petr Štechmüller
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Autor se věnuje primárně programování v Javě, ale nebojí se ani webových technologií.
Aktivity