Java ClassLoader
Java ClassLoader ir abstrakta klase. Tas pieder pie a java.lang iepakojums. Tas ielādē nodarbības no dažādiem resursiem. Java ClassLoader tiek izmantots, lai ielādētu klases izpildes laikā. Citiem vārdiem sakot, JVM izpildes laikā veic saistīšanas procesu. Klases tiek ielādētas JVM atbilstoši vajadzībām. Ja ielādēta klase ir atkarīga no citas klases, tiek ielādēta arī šī klase. Kad mēs pieprasām ielādēt klasi, tā deleģē klasi savam vecākam. Tādā veidā izpildlaika vidē tiek saglabāta unikalitāte. Ir svarīgi izpildīt Java programmu.
git add --all
Java ClassLoader pamatā ir trīs principi: Delegācija , Redzamība , un Unikalitāte .
ClassLoader veidi
Programmā Java katram ClassLoader ir iepriekš noteikta vieta, no kuras tie ielādē klases failus. Java ir šādi ClassLoader veidi:
Bootstrap klases ielādētājs: Tas ielādē standarta JDK klases failus no rt.jar un citām galvenajām klasēm. Tas ir visu klašu iekrāvēju vecāks. Tam nav neviena vecāka. Kad mēs izsaucam String.class.getClassLoader(), tas atgriež nulli, un jebkurš kods, kas balstīts uz to, rada NullPointerException. To sauc arī par Primordial ClassLoader. Tas ielādē klases failus no jre/lib/rt.jar. Piemēram, java.lang pakotnes klase.
Paplašinājumu klases ielādētājs: Tas deleģē klases ielādes pieprasījumu savam vecākam. Ja klases ielāde ir neveiksmīga, tā ielādē klases no jre/lib/ext direktorijas vai jebkura cita direktorija kā java.ext.dirs. To JVM ieviesa sun.misc.Launcher$ExtClassLoader.
Sistēmas klases ielādētājs: Tas ielādē lietojumprogrammām specifiskas klases no vides mainīgā CLASSPATH. To var iestatīt, izsaucot programmu, izmantojot komandrindas opcijas -cp vai classpath. Tas ir paplašinājuma ClassLoader atvasinājums. To īsteno sun.misc.Launcher$AppClassLoader klase. Visi Java ClassLoader ievieš java.lang.ClassLoader.
Kā ClassLoader darbojas Java
Kad JVM pieprasa klasi, tas izsauc java.lang.ClassLoader klases metodi loadClass(), nododot pilnībā klasificēto klases nosaukumu. Metode loadClass() izsauc metodi findLoadedClass(), lai pārbaudītu, vai klase jau ir ielādēta. Ir nepieciešams izvairīties no klases vairākkārtējas ielādes.
Ja klase jau ir ielādēta, tā deleģē pieprasījumu vecākam ClassLoader, lai ielādētu klasi. Ja ClassLoader neatrod klasi, tas izsauc metodi findClass(), lai meklētu klases failu sistēmā. Šajā diagrammā parādīts, kā ClassLoader ielādē klasi Java, izmantojot deleģēšanu.
Pieņemsim, ka mums ir lietojumprogrammai specifiska klase Demo.class. Šīs klases failu ielādes pieprasījums tiek pārsūtīts uz programmu ClassLoader. Tas deleģē savam vecākajam paplašinājuma ClassLoader. Turklāt tas tiek deleģēts Bootstrap ClassLoader. Bootstrap meklējiet šo klasi rt.jar un tā kā šīs klases tur nav. Tagad pieprasiet pārsūtīšanu uz Extension ClassLoader, kas meklē direktoriju jre/lib/ext un mēģina tur atrast šo klasi. Ja klase tur tiek atrasta, paplašinājums ClassLoader ielādē šo klasi. Lietojumprogramma ClassLoader nekad neielādē šo klasi. Ja paplašinājums ClassLoader to neielādē, lietojumprogramma ClaasLoader to ielādē no Java CLASSPATH.
Redzamības princips nosaka, ka bērns ClassLoader var redzēt klasi, ko ielādējis vecāks ClassLoader, bet otrādi tas nav taisnība. Tas nozīmē, ja lietojumprogramma ClassLoader ielādē Demo.class, tādā gadījumā mēģinot tieši ielādēt Demo.class, izmantojot paplašinājumu ClassLoader, tiek izmests java.lang.ClassNotFoundException.
Saskaņā ar unikalitātes principu vecāka ielādētā klase nedrīkst atkārtoti ielādēt Child ClassLoader. Tātad ir iespējams uzrakstīt klases ielādētāju, kas pārkāpj deleģēšanas un unikalitātes principus un ielādē klasi pati par sevi.
Īsāk sakot, klases ielādētājs ievēro šādu noteikumu:
- Tas pārbauda, vai klase jau ir ielādēta.
- Ja klase nav ielādēta, lūdziet vecākklases ielādētājam ielādēt klasi.
- Ja vecākklases ielādētājs nevar ielādēt klasi, mēģiniet to ielādēt šajā klases ielādētājā.
Apsveriet šādu piemēru:
public class Demo { public static void main(String args[]) { System.out.println('How are you?'); } }
Apkopojiet un palaidiet iepriekš minēto kodu, izmantojot šo komandu:
javac Demo.java java -verbose:class Demo
-verbose:class: To izmanto, lai parādītu informāciju par klasēm, ko ielādē JVM. Tas ir noderīgi, ja tiek izmantots klases ielādētājs klašu dinamiskai ielādei. Nākamajā attēlā parādīta izvade.
Varam novērot, ka pirmās tiek ielādētas izpildlaika klases, kas nepieciešamas lietojumprogrammas klasei (Demo).
Kad nodarbības ir ielādētas
Ir tikai divi gadījumi:
- Kad tiek izpildīts jaunais baita kods.
- Kad baita kods veido statisku atsauci uz klasi. Piemēram, System.out .
Statiskā pret dinamisko klases ielādi
Klases tiek statiski ielādētas ar 'jaunu' operatoru. Dinamiskā klases ielāde izpildes laikā izsauc klases ielādētāja funkcijas, izmantojot metodi Class.forName().
Atšķirība starp loadClass() un Class.forName()
Metode loadClass() ielādē tikai klasi, bet neinicializē objektu. Kamēr metode Class.forName() inicializē objektu pēc tā ielādes. Piemēram, ja JDBC draivera ielādei izmantojat ClassLoader.loadClass(), klases ielādētājs neļauj ielādēt JDBC draiveri.
Metode java.lang.Class.forName() atgriež klases objektu kopā ar klasi vai saskarnēm ar doto virknes nosaukumu. Tas izmet ClassNotFoundException, ja klase netiek atrasta.
Piemērs
Šajā piemērā tiek ielādēta klase java.lang.String. Tas izdrukā klases nosaukumu, pakotnes nosaukumu un visu pieejamo String klases metožu nosaukumus. Mēs izmantojam Class.forName() nākamajā piemērā.
Klase: Apzīmē klases objektu, kas var būt jebkura veida (? ir aizstājējzīme). Klases tips satur metainformāciju par klasi. Piemēram, String.class tips ir Class. Izmantojiet Class, ja modelējamā klase nav zināma.
getDeclaredMethod(): Atgriež masīvu, kurā ir Metodes objekti, kas atspoguļo visas deklarētās klases vai interfeisa metodes, kuras attēlo šis klases objekts, tostarp publiskās, aizsargātās, noklusējuma (pakotnes) piekļuves un privātās metodes, bet izslēdzot mantotās metodes.
getName(): Tas atgriež metodes nosaukumu, ko attēlo šis Metodes objekts, kā virkni.
import java.lang.reflect.Method; public class ClassForNameExample { public static void main(String[] args) { try { Class cls = Class.forName('java.lang.String'); System.out.println('Class Name: ' + cls.getName()); System.out.println('Package Name: ' + cls.getPackage()); Method[] methods = cls.getDeclaredMethods(); System.out.println('-----Methods of String class -------------'); for (Method method : methods) { System.out.println(method.getName()); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
Izvade
Class Name: java.lang.String Package Name: package java.lang -----Methods of String class ------------- value coder equals length toString hashCode getChars ------ ------ ------ intern isLatin1 checkOffset checkBoundsOffCount checkBoundsBeginEnd access0 access0