logo

ClassLoader a Java

Java ClassLoader

Java ClassLoader és una classe abstracta. Pertany a a java.lang paquet. Carrega classes de diferents recursos. Java ClassLoader s'utilitza per carregar les classes en temps d'execució. En altres paraules, JVM realitza el procés d'enllaç en temps d'execució. Les classes es carreguen a la JVM segons les necessitats. Si una classe carregada depèn d'una altra classe, aquesta classe també es carrega. Quan demanem carregar una classe, delega la classe al seu pare. D'aquesta manera, es manté la singularitat en l'entorn d'execució. És imprescindible executar un programa Java.

js cadena multilínia
ClassLoader a Java

Java ClassLoader es basa en tres principis: Delegació , Visibilitat , i Unicitat .

    Principi de delegació:Reenvia la sol·licitud de càrrega de classes al carregador de classes pare. Només carrega la classe si el pare no la troba ni la carrega.Principi de visibilitat:Permet al carregador de classes fills veure totes les classes carregades pel ClassLoader pare. Però el carregador de classes pare no pot veure les classes carregades pel carregador de classes fills.Principi d'unicitat:Permet carregar una classe una vegada. S'aconsegueix pel principi de delegació. Assegura que el ClassLoader fill no recarregui la classe, que ja està carregada pel pare.

Tipus de ClassLoader

A Java, cada ClassLoader té una ubicació predefinida des d'on carreguen els fitxers de classe. Hi ha els següents tipus de ClassLoader a Java:

Carregador de classe Bootstrap: Carrega fitxers de classe JDK estàndard des de rt.jar i altres classes bàsiques. És un pare de tots els carregadors de classe. No té cap pare. Quan cridem a String.class.getClassLoader() retorna null i qualsevol codi basat en ell genera NullPointerException. També s'anomena Primordial ClassLoader. Carrega fitxers de classe des de jre/lib/rt.jar. Per exemple, classe de paquet java.lang.

Carregador de classes d'extensions: Delega la sol·licitud de càrrega de classe al seu pare. Si la càrrega d'una classe no té èxit, carrega les classes des del directori jre/lib/ext o qualsevol altre directori com a java.ext.dirs. Està implementat per sun.misc.Launcher$ExtClassLoader a JVM.

Carregador de classes del sistema: Carrega classes específiques de l'aplicació des de la variable d'entorn CLASSPATH. Es pot configurar mentre s'invoca el programa mitjançant les opcions de línia d'ordres -cp o classpath. És un fill d'Extension ClassLoader. Està implementat per la classe sun.misc.Launcher$AppClassLoader. Tot Java ClassLoader implementa java.lang.ClassLoader.

ClassLoader a Java

Com funciona ClassLoader a Java

Quan la JVM sol·licita una classe, invoca un mètode loadClass() de la classe java.lang.ClassLoader passant el nom totalment classificat de la classe. El mètode loadClass() demana el mètode findLoadedClass() per comprovar que la classe ja s'ha carregat o no. Cal evitar carregar la classe diverses vegades.

Si la classe ja està carregada, delega la sol·licitud al ClassLoader principal per carregar la classe. Si el ClassLoader no troba la classe, invoca el mètode findClass() per cercar les classes al sistema de fitxers. El diagrama següent mostra com ClassLoader carrega classe a Java mitjançant la delegació.

ClassLoader a Java

Suposem que tenim una classe específica de l'aplicació Demo.class. La sol·licitud de càrrega d'aquests fitxers de classe es transfereix a l'aplicació ClassLoader. Delega a la seva extensió principal ClassLoader. A més, delega a Bootstrap ClassLoader. Bootstrap cerca aquesta classe a rt.jar i ja que aquesta classe no hi és. Ara sol·liciteu la transferència a l'extensió ClassLoader que cerca el directori jre/lib/ext i intenta localitzar-hi aquesta classe. Si la classe es troba allà, Extension ClassLoader carrega aquesta classe. L'aplicació ClassLoader mai carrega aquesta classe. Quan l'extensió ClassLoader no la carrega, l'aplicació ClaasLoader la carrega des de CLASSPATH a Java.

El principi de visibilitat estableix que el ClassLoader fill pot veure la classe carregada pel ClassLoader pare, però viceversa no és cert. Vol dir que si l'aplicació ClassLoader carrega Demo.class, en aquest cas, intentant carregar Demo.class de manera explícita mitjançant l'extensió ClassLoader llança java.lang.ClassNotFoundException.

Segons el principi d'unicitat, Child ClassLoader no hauria de tornar a carregar una classe carregada pel pare. Per tant, és possible escriure un carregador de classes que infringeixi els principis de delegació i unicitat i carrega la classe per si mateix.

En resum, el carregador de classes segueix la següent regla:

  • Comprova si la classe ja està carregada.
  • Si la classe no està carregada, demaneu al carregador de classe pare que carregui la classe.
  • Si el carregador de classes pare no pot carregar la classe, intenteu carregar-la en aquest carregador de classes.

Considereu l'exemple següent:

 public class Demo { public static void main(String args[]) { System.out.println('How are you?'); } } 

Compileu i executeu el codi anterior mitjançant l'ordre següent:

 javac Demo.java java -verbose:class Demo 

-verbose:class: S'utilitza per mostrar la informació sobre les classes que està carregant la JVM. És útil quan s'utilitza el carregador de classes per carregar classes dinàmicament. La figura següent mostra la sortida.

ClassLoader a Java

Podem observar que primer es carreguen les classes d'execució requerides per la classe d'aplicació (Demo).

Quan es carreguen les classes

Només hi ha dos casos:

  • Quan s'executa el nou codi de bytes.
  • Quan el codi de bytes fa una referència estàtica a una classe. Per exemple, System.out .

Càrrega de classe estàtica i dinàmica

Les classes es carreguen estàticament amb l'operador 'nou'. La càrrega dinàmica de classes invoca les funcions d'un carregador de classes en temps d'execució mitjançant el mètode Class.forName().

Diferència entre loadClass() i Class.forName()

El mètode loadClass() només carrega la classe però no inicialitza l'objecte. Mentre que el mètode Class.forName() inicialitza l'objecte després de carregar-lo. Per exemple, si utilitzeu ClassLoader.loadClass() per carregar el controlador JDBC, el carregador de classes no permet carregar el controlador JDBC.

El mètode java.lang.Class.forName() retorna l'objecte de classe juntament amb la classe o les interfícies amb el nom de cadena donat. Llança ClassNotFoundException si no es troba la classe.

Exemple

En aquest exemple, es carrega la classe java.lang.String. Imprimeix el nom de la classe, el nom del paquet i els noms de tots els mètodes disponibles de la classe String. Estem utilitzant Class.forName() a l'exemple següent.

Classe: Representa un objecte Class que pot ser de qualsevol tipus (? és un comodí). El tipus de classe conté metainformació sobre una classe. Per exemple, el tipus de String.class és Class. Utilitzeu Class si la classe que s'està modelant és desconeguda.

getDeclaredMethod(): Retorna una matriu que conté objectes Method que reflecteixen tots els mètodes declarats de la classe o interfície representada per aquest objecte Class, inclosos els mètodes públics, protegits, per defecte (de paquet) i privats, però excloent els mètodes heretats.

getName(): Retorna el nom del mètode representat per aquest objecte Method, com una cadena.

 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(); } } } 

Sortida

 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