Che cos'è un ClassLoader Java?


174

In poche semplici frasi, cos'è un ClassLoader Java, quando viene utilizzato e perché?

OK, ho letto un articolo wiki. ClassLoader carica le classi. OK. Quindi, se includo i file jar e l'importazione, un ClassLoader fa il lavoro.

Perché dovrei preoccuparmi di questo ClassLoader? Non l'ho mai usato e non sapevo che esistesse.

La domanda è: perché esiste la classe ClassLoader? Inoltre, come lo usi in pratica? (I casi esistono, lo so.)


Otterrai risultati migliori se restringi la tua domanda, ad esempio indicando una parte specifica che non capisci, come si riferisce a un'altra lingua che conosci, ecc.
JRL

75
Questa è una domanda del tutto ragionevole, vista dal punto di vista di qualcuno che cerca alcune semplici frasi per spiegare il concetto
oxbow_lakes

Questo video potrebbe essere di interesse: ottieni davvero caricatori di classi?
asmaier,

Risposte:


231

Tratto da questo bel tutorial di Sun:

Motivazione

Le applicazioni scritte in linguaggi di programmazione compilati staticamente, come C e C ++, vengono compilate in istruzioni native specifiche della macchina e salvate come file eseguibile. Il processo di combinazione del codice in un codice nativo eseguibile è chiamato collegamento: l'unione del codice compilato separatamente con il codice della libreria condivisa per creare un'applicazione eseguibile. Ciò è diverso nei linguaggi di programmazione compilati dinamicamente come Java. In Java, i file .class generati dal compilatore Java rimangono così come sono fino a quando non vengono caricati nella Java Virtual Machine (JVM) - in altre parole, il processo di collegamento viene eseguito dalla JVM in fase di esecuzione. Le classi vengono caricate nella JVM su una base 'secondo necessità'. E quando una classe caricata dipende da un'altra classe, anche quella classe viene caricata.

Quando viene avviata un'applicazione Java, la prima classe da eseguire (o il punto di ingresso nell'applicazione) è quella con metodo vuoto statico pubblico chiamato main (). Questa classe di solito ha riferimenti ad altre classi e tutti i tentativi di caricare le classi di riferimento vengono eseguiti dal programma di caricamento classi.

Per avere un'idea di questo caricamento di classe ricorsivo e dell'idea di caricamento di classe in generale, considera la seguente semplice classe:

public class HelloApp {
   public static void main(String argv[]) {
      System.out.println("Aloha! Hello and Bye");
   }
}

Se si esegue questa classe specificando l'opzione della riga di comando -verbose: class, in modo che stampa quali classi vengono caricate, si otterrà un output simile al seguente. Si noti che questo è solo un output parziale poiché l'elenco è troppo lungo per essere mostrato qui.

prmpt>java -verbose:class HelloApp



[Opened C:\Program Files\Java\jre1.5.0\lib\rt.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\jsse.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\jce.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\charsets.jar]
[Loaded java.lang.Object from shared objects file]
[Loaded java.io.Serializable from shared objects file]
[Loaded java.lang.Comparable from shared objects file]
[Loaded java.lang.CharSequence from shared objects file]
[Loaded java.lang.String from shared objects file]
[Loaded java.lang.reflect.GenericDeclaration from shared objects file]
[Loaded java.lang.reflect.Type from shared objects file]
[Loaded java.lang.reflect.AnnotatedElement from shared objects file]
[Loaded java.lang.Class from shared objects file]
[Loaded java.lang.Cloneable from shared objects file]
[Loaded java.lang.ClassLoader from shared objects file]
[Loaded java.lang.System from shared objects file]
[Loaded java.lang.Throwable from shared objects file]
.
.
.
[Loaded java.security.BasicPermissionCollection from shared objects file]
[Loaded java.security.Principal from shared objects file]
[Loaded java.security.cert.Certificate from shared objects file]
[Loaded HelloApp from file:/C:/classes/]
Aloha! Hello and Bye
[Loaded java.lang.Shutdown from shared objects file]
[Loaded java.lang.Shutdown$Lock from shared objects file]

Come puoi vedere, le classi di runtime Java richieste dalla classe di applicazione (HelloApp) vengono caricate per prime.

Caricatori di classi nella piattaforma Java 2

Il linguaggio di programmazione Java continua a evolversi per semplificare la vita degli sviluppatori di applicazioni ogni giorno. Questo viene fatto fornendo API che ti semplificano la vita permettendoti di concentrarti sulla logica aziendale piuttosto che sui dettagli di implementazione dei meccanismi fondamentali. Ciò è evidente dal recente passaggio da J2SE 1.5 a J2SE 5.0 al fine di riflettere la maturità della piattaforma Java.

A partire da JDK 1.2, un caricatore di classi bootstrap incorporato in JVM è responsabile del caricamento delle classi del runtime Java. Questo caricatore di classi carica solo le classi che si trovano nel percorso di classe di avvio e poiché si tratta di classi affidabili, il processo di convalida non viene eseguito come per le classi non attendibili. Oltre al caricatore di classi bootstrap, JVM dispone di un caricatore di classi di estensioni responsabile del caricamento di classi dalle API di estensioni standard e di un caricatore di classi di sistema che carica le classi da un percorso di classe generale e dalle classi dell'applicazione.

Poiché esiste più di un caricatore di classi, sono rappresentati in un albero la cui radice è il caricatore di classi bootstrap. Ogni caricatore di classi ha un riferimento al proprio caricatore di classi principale. Quando viene richiesto a un caricatore di classi di caricare una classe, consulta il proprio caricatore di classi principale prima di tentare di caricare l'elemento stesso. Il genitore a sua volta consulta il suo genitore e così via. Quindi è solo dopo che tutti i caricatori di classi di antenati non riescono a trovare la classe che viene coinvolto l'attuale caricatore di classi. In altre parole, viene utilizzato un modello di delega.

La classe java.lang.ClassLoader

La java.lang.ClassLoaderè una classe astratta che può essere sottoclassi dalle applicazioni che necessitano di estendere il modo in cui la JVM dinamicamente classi carichi. I costruttori in java.lang.ClassLoader(e le sue sottoclassi) consentono di specificare un genitore quando si crea un'istanza di un nuovo caricatore di classi. Se non si specifica esplicitamente un genitore, il caricatore di classi di sistema della macchina virtuale verrà assegnato come genitore predefinito. In altre parole, la classe ClassLoader utilizza un modello di delega per cercare classi e risorse. Pertanto, ogni istanza di ClassLoader ha un programma di caricamento classi padre associato, in modo che quando viene richiesto di trovare una classe o risorse, l'attività viene delegata al programma di caricamento classe padre prima di tentare di trovare la classe o la risorsa stessa. Il loadClass()metodo di ClassLoader esegue le seguenti attività, in ordine, quando viene chiamato per caricare una classe:

Se una classe è già stata caricata, la restituisce. Altrimenti, delega la ricerca della nuova classe al programma di caricamento classi genitore. Se il programma di caricamento classi genitore non trova la classe, loadClass()chiama il metodo findClass()per trovare e caricare la classe. Il finalClass()metodo cerca la classe nel programma di caricamento classi corrente se la classe non è stata trovata dal programma di caricamento classi padre.


C'è di più nell'articolo originale, che mostra anche come implementare i propri caricatori di classi di rete, che risponde alla tua domanda sul perché (e come). Vedi anche i documenti API .


47

La maggior parte degli sviluppatori Java non avrà mai bisogno di usare esplicitamente i caricatori di classi (tranne per caricare le risorse in modo che funzioni ancora quando sono raggruppati in JAR), per non parlare di scrivere il proprio.

ClassLoaders sono utilizzati in grandi sistemi e applicazioni server per fare cose come:

  • Modularizza un sistema e carica, scarica e aggiorna i moduli in fase di esecuzione
  • Utilizzare in parallelo diverse versioni di una libreria API (ad es. Un parser XML)
  • Isola diverse applicazioni in esecuzione all'interno della stessa JVM (assicurando che non interferiscano l'una con l'altra, ad esempio attraverso variabili statiche)

29

La domanda è "Perché dovremmo disturbare questa classe ClassLoader"?

Bene, soprattutto così puoi sistemare le cose se vanno male :-).

È vero, basta che tu scriva un'applicazione, la compili in un JAR e magari includa alcuni JAR di libreria aggiuntivi, non devi conoscere i caricatori di classi, funzionerà.

Tuttavia, è utile conoscere un po 'i caricatori di classe e il caricamento di classe per capire meglio cosa succede dietro le quinte. Ad esempio, gli "inizializzatori statici" verranno eseguiti quando viene caricata una classe, quindi per capire quando verranno eseguiti, è necessario sapere come il caricatore di classi decide quando caricarli.

anche .. come lo usi in pratica?

Per casi semplici, non hai bisogno di loro. Tuttavia, se è necessario caricare il codice in modo dinamico in fase di esecuzione con controllo esplicito da cui proviene (ad esempio caricamento in rete, caricamento di plug-in non disponibili al momento della compilazione, ecc.), Potrebbe essere necessario fare di più. Quindi puoi ad esempio scrivere il tuo caricatore di classi. Vedi le altre risposte per i collegamenti.


14

ClassLoaderin Java è una classe che viene utilizzata per caricare i file di classe in Java. Il codice Java viene compilato nel file di classe dal javaccompilatore e JVM esegue il programma Java, eseguendo i codici byte scritti nel file di classe.

ClassLoader è responsabile del caricamento dei file di classe dal file system, dalla rete o da qualsiasi altra fonte. Esistono tre caricatori di classi predefiniti utilizzati in Java, Bootstrap , Extension e System o Caricatore di classi di applicazioni .

ClassLoader


Come funziona ClassLoader

## ClassLoader interazione con JVM inserisci qui la descrizione dell'immagine

Altro @: how-classloader-works-in-java.html


6

Caricatori di classi sono un componente funzionale di JVM, che carica i dati di classe dal file '.class' o dalla rete nell'area del metodo in Heap.

Sembra una parte integrante della JVM, ma come utente java finale perché dovrei preoccuparmi? Ecco perché:

Ogni caricatore di classi ha il proprio spazio dei nomi e le classi invocate da un particolare caricatore di classi entrano nel suo spazio dei nomi.

Le classi invocate da due diversi caricatori di classi non avranno visibilità l'una sull'altra, con conseguente maggiore sicurezza.

Il meccanismo di delega figlio padre del caricatore di classi garantisce che le classi Java API non possano mai essere hackerate da codice non autorizzato.

Per i dettagli guarda qui


1

I caricatori di classi sono gerarchici. Le classi vengono introdotte nella JVM in quanto sono referenziate per nome in una classe che è già in esecuzione nella JVM.

Come veniva caricata la primissima classe?
La primissima classe viene caricata con l'aiuto del static main()metodo dichiarato nella tua classe. Tutte le classi caricate successivamente vengono caricate dalle classi, che sono già caricate e in esecuzione.

Un programma di caricamento classi crea uno spazio dei nomi. Tutte le JVM includono almeno un caricatore di classi incorporato nella JVM chiamato caricatore di classi primordiale (o bootstrap) . Questa è una cosa e vedremo i caricatori di classi non primordiali. La JVM ha degli hook per consentire l'utilizzo dei caricatori di classi definiti dall'utente al posto del caricatore di classi primordiali. Ecco i caricatori di classi creati da JVM.

Bootstrap (primordiale) Questo caricatore di classi non è ricaricabile. Carica le classi interne JDK, i pacchetti java. * (In genere carica rt.jar e i18n.jar). Estensioni Questo caricatore di classi non è ricaricabile. Carica i file jar dalla directory delle estensioni JDK (di solito lib / ext di JRE). Sistema Questo caricatore di classi non è ricaricabile. Carica le classi dal percorso della classe di sistema.

http://www.sbalasani.com/2015/01/java-class-loaders.html


1

Quando ti chiedi perché esiste la classe ClassLoader, il motivo è piuttosto semplice: è la classe responsabile di trovare e caricare i file di classe in fase di esecuzione .

Elaboriamo.

In JVM, ogni classe è caricata da qualche istanza di java.lang.ClassLoader. Ogni volta che una nuova JVM viene avviata dal solito java <classname>comando di avvio del programma Java , il primo passo è caricare tutte le classi chiave in memoria richieste per il corretto funzionamento come java.lang.Objecte altre classi di runtime ( rt.jar).

Ora, in ClassLoader ci sono in realtà 3 parti:

  • Il BootstrapClassLoaderè responsabile per rendere queste classi disponibili, ovvero loading queste classi nella memoria.

  • Il prossimo compito è caricare eventuali librerie / JAR esterni nella memoria per il corretto funzionamento dell'applicazione. Il ExtClassLoaderresponsabile di questo compito. Questo caricatore di classi è responsabile del caricamento di tutti i file .jar citati nel percorso java.ext.dirs.

  • Il terzo e il principale caricatore di classe importante è il AppClassLoader. Il caricatore di classi di applicazioni è responsabile del caricamento dei file di classe menzionati nella proprietà di sistema java.class.path.

È anche importante notare che le implementazioni ClassLoader predefinite potrebbero essere ignorate consentendo di personalizzare la JVM in modi utili e interessanti, consentendo di ridefinire completamente il modo in cui i file di classe vengono introdotti nel sistema.

inserisci qui la descrizione dell'immagine

Dai un'occhiata per saperne di più su Java Class Loader .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.