logo

ClassLoader in Java

Caricatore di classi Java

Java ClassLoader è una classe astratta. Appartiene ad a java.lang pacchetto. Carica classi da diverse risorse. Java ClassLoader viene utilizzato per caricare le classi in fase di esecuzione. In altre parole, JVM esegue il processo di collegamento in fase di esecuzione. Le classi vengono caricate nella JVM in base alle necessità. Se una classe caricata dipende da un'altra classe, viene caricata anche quella classe. Quando chiediamo di caricare una classe, delega la classe al suo genitore. In questo modo, l'unicità viene mantenuta nell'ambiente runtime. È essenziale eseguire un programma Java.

tutorial sulla scintilla
ClassLoader in Java

Java ClassLoader si basa su tre principi: Delegazione , Visibilità , E Unicità .

    Principio della delega:Inoltra la richiesta di caricamento della classe al caricatore della classe genitore. Carica la classe solo se il genitore non trova o carica la classe.Principio di visibilità:Consente al caricatore di classi figlio di vedere tutte le classi caricate dal ClassLoader genitore. Ma il caricatore di classi genitore non può vedere le classi caricate dal caricatore di classi figlio.Principio di unicità:Permette di caricare una classe una volta. Si ottiene mediante il principio di delega. Garantisce che il ClassLoader figlio non ricarichi la classe, che è già caricata dal genitore.

Tipi di ClassLoader

In Java, ogni ClassLoader ha una posizione predefinita da cui carica i file di classe. Esistono i seguenti tipi di ClassLoader in Java:

Caricatore di classi Bootstrap: Carica file di classe JDK standard da rt.jar e altre classi principali. È un genitore di tutti i caricatori di classi. Non ha alcun genitore. Quando chiamiamo String.class.getClassLoader() restituisce null e qualsiasi codice basato su di esso lancia NullPointerException. È anche chiamato Primordial ClassLoader. Carica i file di classe da jre/lib/rt.jar. Ad esempio, la classe del pacchetto java.lang.

Caricatore classi estensioni: Delega la richiesta di caricamento della classe al suo genitore. Se il caricamento di una classe non ha successo, carica le classi dalla directory jre/lib/ext o da qualsiasi altra directory come java.ext.dirs. È implementato da sun.misc.Launcher$ExtClassLoader in JVM.

Caricatore classi di sistema: Carica classi specifiche dell'applicazione dalla variabile di ambiente CLASSPATH. Può essere impostato durante il richiamo del programma utilizzando le opzioni della riga di comando -cp o classpath. È un figlio dell'estensione ClassLoader. È implementato dalla classe sun.misc.Launcher$AppClassLoader. Tutti i Java ClassLoader implementano java.lang.ClassLoader.

ClassLoader in Java

Come funziona ClassLoader in Java

Quando JVM richiede una classe, richiama un metodo loadClass() della classe java.lang.ClassLoader passando il nome completamente classificato della classe. Il metodo loadClass() richiama il metodo findLoadedClass() per verificare che la classe sia già stata caricata o meno. È necessario per evitare di caricare la lezione più volte.

Se la classe è già caricata, delega la richiesta al genitore ClassLoader per caricare la classe. Se ClassLoader non trova la classe, richiama il metodo findClass() per cercare le classi nel file system. Il diagramma seguente mostra come ClassLoader carica la classe in Java utilizzando la delega.

ClassLoader in Java

Supponiamo di avere una classe specifica dell'applicazione Demo.class. La richiesta di caricamento dei file di questa classe viene trasferita all'Application ClassLoader. Delega al suo genitore Extension ClassLoader. Inoltre, delega a Bootstrap ClassLoader. Bootstrap cerca quella classe in rt.jar e poiché quella classe non è presente. Ora richiedi il trasferimento a Extension ClassLoader che cerca la directory jre/lib/ext e tenta di individuare lì questa classe. Se la classe viene trovata lì, Extension ClassLoader carica quella classe. L'Application ClassLoader non carica mai quella classe. Quando l'estensione ClassLoader non lo carica, l'applicazione ClaasLoader lo carica da CLASSPATH in Java.

Il principio di visibilità afferma che il ClassLoader figlio può vedere la classe caricata dal ClassLoader genitore, ma non è vero il contrario. Significa che se Application ClassLoader carica Demo.class, in tal caso, tentando di caricare Demo.class in modo esplicito utilizzando Extension ClassLoader lancia java.lang.ClassNotFoundException.

Secondo il principio di unicità, una classe caricata dal genitore non dovrebbe essere caricata nuovamente dal Child ClassLoader. Pertanto, è possibile scrivere un caricatore di classi che viola i principi di delega e unicità e carica la classe da sola.

In breve, il caricatore di classi segue la seguente regola:

  • Controlla se la classe è già caricata.
  • Se la classe non viene caricata, chiedi al caricatore della classe genitore di caricare la classe.
  • Se il caricatore di classi genitore non riesce a caricare la classe, prova a caricarla in questo caricatore di classi.

Considera il seguente esempio:

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

Compila ed esegui il codice precedente utilizzando il seguente comando:

 javac Demo.java java -verbose:class Demo 

-verbose:classe: Viene utilizzato per visualizzare le informazioni sulle classi caricate da JVM. È utile quando si utilizza il caricatore di classi per caricare le classi in modo dinamico. La figura seguente mostra l'output.

ClassLoader in Java

Possiamo osservare che le classi runtime richieste dalla classe dell'applicazione (Demo) vengono caricate per prime.

Quando le lezioni vengono caricate

Ci sono solo due casi:

  • Quando viene eseguito il nuovo codice byte.
  • Quando il codice byte fa un riferimento statico a una classe. Per esempio, Sistema.out .

Caricamento di classi statico e dinamico

Le classi vengono caricate staticamente con l'operatore 'new'. Il caricamento dinamico delle classi richiama le funzioni di un caricatore di classi in fase di esecuzione utilizzando il metodo Class.forName().

Differenza tra loadClass() e Class.forName()

Il metodo loadClass() carica solo la classe ma non inizializza l'oggetto. Mentre il metodo Class.forName() inizializza l'oggetto dopo averlo caricato. Ad esempio, se si utilizza ClassLoader.loadClass() per caricare il driver JDBC, il caricatore di classi non consente di caricare il driver JDBC.

Il metodo java.lang.Class.forName() restituisce l'oggetto classe accoppiato alla classe o alle interfacce con il nome della stringa fornita. Lancia ClassNotFoundException se la classe non viene trovata.

Esempio

In questo esempio viene caricata la classe java.lang.String. Stampa il nome della classe, il nome del pacchetto e i nomi di tutti i metodi disponibili della classe String. Stiamo utilizzando Class.forName() nell'esempio seguente.

Classe: Rappresenta un oggetto Classe che può essere di qualsiasi tipo (? è un carattere jolly). Il tipo Classe contiene metainformazioni su una classe. Ad esempio, il tipo di String.class è Class. Utilizza Class se la classe da modellare è sconosciuta.

getDeclaredMethod(): Restituisce un array contenente oggetti Method che riflettono tutti i metodi dichiarati della classe o dell'interfaccia rappresentata da questo oggetto Class, inclusi i metodi pubblici, protetti, di accesso predefiniti (pacchetto) e privati, ma escludendo i metodi ereditati.

getNome(): Restituisce il nome del metodo rappresentato da questo oggetto Method, come String.

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

Produzione

 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