Java Language
Il percorso di classe
Ricerca…
introduzione
Osservazioni
Caricamento della classe Java
La JVM (Java Virtual Machine) caricherà le classi come e quando sono richieste le classi (questo è chiamato lazy-loading). Le posizioni delle classi da utilizzare sono specificate in tre punti: -
- Quelli richiesti dalla piattaforma Java vengono caricati per primi, come quelli nella libreria di classi Java e le sue dipendenze.
- Le classi di estensione vengono caricate successivamente (cioè quelle in
jre/lib/ext/
) - Vengono quindi caricate le classi definite dall'utente tramite il classpath
Le classi vengono caricate usando classi che sono sottotipi di java.lang.ClassLoader
. Questo è descritto più in dettaglio in questo argomento: Classloader .
classpath
Il classpath è un parametro utilizzato dalla JVM o dal compilatore che specifica le posizioni delle classi e dei pacchetti definiti dall'utente. Questo può essere impostato nella riga di comando come con la maggior parte di questi esempi o attraverso una variabile ambientale ( CLASSPATH
)
Diversi modi per specificare il classpath
Esistono tre modi per impostare il classpath.
Può essere impostato utilizzando la
CLASSPATH
ambienteCLASSPATH
:set CLASSPATH=... # Windows and csh export CLASSPATH=... # Unix ksh/bash
Può essere impostato sulla riga di comando come segue
java -classpath ... javac -classpath ...
Si noti che l'
-classpath
(o-cp
) ha la precedenza sullaCLASSPATH
ambienteCLASSPATH
.Il percorso di classe per un file JAR eseguibile viene specificato utilizzando l'elemento
Class-Path
inMANIFEST.MF
:Class-Path: jar1-name jar2-name directory-name/jar3-name
Si noti che questo si applica solo quando il file JAR viene eseguito in questo modo:
java -jar some.jar ...
In questa modalità di esecuzione, l'opzione
-classpath
e la variabile di ambiente CLASSPATH verranno ignorate, anche se il file JAR non ha un elementoClass-Path
.
Se non viene specificato alcun percorso di classe, il percorso di classe predefinito è il file JAR selezionato quando si utilizza java -jar
o altrimenti la directory corrente.
Relazionato:
- https://docs.oracle.com/javase/tutorial/deployment/jar/downman.html
- http://docs.oracle.com/javase/7/docs/technotes/tools/windows/classpath.html
Aggiunta di tutti i JAR in una directory al classpath
Se si desidera aggiungere tutti i JAR nella directory al classpath, è possibile farlo concisamente utilizzando la sintassi dei caratteri jolly di classpath; per esempio:
someFolder/*
Questo dice alla JVM di aggiungere tutti i file JAR e ZIP nella directory someFolder
al classpath. Questa sintassi può essere utilizzata in un argomento -cp
, in una CLASSPATH
ambiente CLASSPATH
o in un attributo Class-Path
in un file manifest di un file JAR eseguibile. Vedere Impostazione del percorso di classe: Wildcard del percorso di classe per esempi e avvertimenti.
Gli appunti:
- I caratteri jolly di Classpath sono stati introdotti per la prima volta in Java 6. Le versioni precedenti di Java non trattano "*" come carattere jolly.
- Non puoi mettere altri personaggi prima o dopo " "; es. "someFolder / .jar" non è un jolly.
- Un carattere jolly corrisponde solo ai file con il suffisso ".jar" o ".JAR". I file ZIP vengono ignorati, così come i file JAR con suffissi diversi.
- Un carattere jolly corrisponde solo ai file JAR nella directory stessa, non nelle sue sottodirectory.
- Quando un gruppo di file JAR è abbinato a una voce jolly, il loro ordine relativo sul classpath non viene specificato.
Sintassi del percorso del percorso di classe
Il classpath è una sequenza di voci che sono nomi di percorsi di directory, nomi di percorsi file JAR o ZIP o specifiche jolly JAR / ZIP.
Per un classpath specificato sulla riga di comando (ad esempio
-classpath
) o come variabile di ambiente, le voci devono essere separate con;
(punto e virgola) caratteri su Windows, o:
(due punti) caratteri su altre piattaforme (Linux, UNIX, MacOSX e così via).Per l'elemento
Class-Path
inMANIFEST.MF
di un file JAR, utilizzare un singolo spazio per separare le voci.
A volte è necessario incorporare uno spazio in una voce classpath
Quando il classpath è specificato sulla riga di comando, si tratta semplicemente di utilizzare il quoting della shell appropriato. Per esempio:
export CLASSPATH="/home/user/My JAR Files/foo.jar:second.jar"
(I dettagli possono dipendere dalla shell dei comandi che usi).
Quando il classpath viene specificato in un file JAR come file "MANIFEST.MF", è necessario utilizzare la codifica URL.
Class-Path: /home/user/My%20JAR%20Files/foo.jar second.jar
Percorso di classe dinamico
A volte, l'aggiunta di tutti i JAR da una cartella non è sufficiente, ad esempio quando si dispone di codice nativo e occorre selezionare un sottoinsieme di JAR. In questo caso, sono necessari due metodi main()
. Il primo costruisce un classloader e quindi usa questo classloader per chiamare il secondo main()
.
Ecco un esempio che seleziona il JAR nativo SWT corretto per la piattaforma, aggiunge tutti i JAR dell'applicazione e quindi richiama il metodo main()
reale: Creazione di un'applicazione SWT Java multipiattaforma
Carica una risorsa dal classpath
Può essere utile caricare una risorsa (immagine, file di testo, proprietà, KeyStore, ...) che è impacchettata all'interno di un JAR. A tale scopo, possiamo usare Class
e ClassLoader
.
Supponiamo di avere la seguente struttura di progetto:
program.jar
|
\-com
\-project
|
|-file.txt
\-Test.class
E vogliamo accedere ai contenuti di file.txt
dalla classe Test
. Possiamo farlo chiedendo al classloader:
InputStream is = Test.class.getClassLoader().getResourceAsStream("com/project/file.txt");
Usando il classloader, dobbiamo specificare il percorso completo della nostra risorsa (ciascun pacchetto).
In alternativa, possiamo chiedere direttamente all'oggetto della classe Test
InputStream is = Test.class.getResourceAsStream("file.txt");
Usando l'oggetto classe, il percorso è relativo alla classe stessa. Il nostro Test.class
è nel pacchetto com.project
, lo stesso di file.txt
, non abbiamo bisogno di specificare alcun percorso.
Possiamo, tuttavia, utilizzare percorsi assoluti dall'oggetto classe, in questo modo:
is = Test.class.getResourceAsStream("/com/project/file.txt");
Mappatura dei nomi di classe ai nomi di percorso
La toolchain Java standard (e strumenti di terze parti progettati per interagire con essi) hanno regole specifiche per mappare i nomi delle classi ai nomi dei percorsi dei file e altre risorse che li rappresentano.
Le mappature sono le seguenti
- Per le classi nel pacchetto predefinito, i nomi di percorso sono nomi di file semplici.
- Per le classi in un pacchetto denominato, i componenti del nome del pacchetto vengono mappati nelle directory.
- Per le classi nidificate e interne nominate, il componente nomefile viene formato unendo i nomi di classe con un carattere
$
. - Per le classi interne anonime, i numeri vengono utilizzati al posto dei nomi.
Questo è illustrato nella seguente tabella:
Nome della classe | Percorso di origine | Classfile pathname |
---|---|---|
SomeClass | SomeClass.java | SomeClass.class |
com.example.SomeClass | com/example/SomeClass.java | com/example/SomeClass.class |
SomeClass.Inner | (in SomeClass.java ) | SomeClass$Inner.class |
SomeClass interni anon di SomeClass | (in SomeClass.java ) | SomeClass$1.class , SomeClass$2.class , ecc |
Cosa significa classpath: come funzionano le ricerche
Lo scopo del classpath è di dire a una JVM dove trovare classi e altre risorse. Il significato del classpath e del processo di ricerca sono intrecciati.
Il classpath è una forma di percorso di ricerca che specifica una sequenza di posizioni in cui cercare le risorse. In un classpath standard, queste posizioni sono o una directory nel file system host, un file JAR o un file ZIP. In ogni caso, la posizione è la radice di uno spazio dei nomi che verrà cercato.
La procedura standard per la ricerca di una classe sul classpath è la seguente:
Mappare il nome della classe in un percorso di file relativo relativo
RP
. Il mapping dei nomi di classi ai nomi di classe è descritto altrove.Per ogni voce
E
nel classpath:- Se la voce è una directory del filesystem:
- Risolvi
RP
rispetto aE
per dare unAP
assoluto. - Verifica se
AP
è un percorso per un file esistente. - Se sì, carica la classe da quel file
- Risolvi
- Se la voce è un file JAR o ZIP:
- Cerca
RP
nell'indice del file JAR / ZIP. - Se la voce del file JAR / ZIP corrispondente esiste, caricare la classe da quella voce.
- Cerca
- Se la voce è una directory del filesystem:
La procedura per cercare una risorsa sul classpath dipende dal fatto che il percorso della risorsa sia assoluto o relativo. Per un percorso di risorse assoluto, la procedura è come sopra. Per un percorso di risorse relativo risolto utilizzando Class.getResource
o Class.getResourceAsStream
, il percorso per il pacchetto di classi viene anteposto prima della ricerca.
(Nota: queste sono le procedure implementate dai classloader Java standard. Un classloader personalizzato potrebbe eseguire la ricerca in modo diverso).
Il percorso di classe di bootstrap
I normali classloader Java cercano prima le classi nel percorso di classe bootstrap, prima di cercare le estensioni e il classpath dell'applicazione. Per impostazione predefinita, il percorso di classe bootstrap è costituito dal file "rt.jar" e da altri file JAR importanti forniti dall'installazione di JRE. Questi forniscono tutte le classi nella libreria di classi Java SE standard, insieme a varie classi di implementazione "interne".
In circostanze normali, non è necessario preoccuparsi di questo. Per impostazione predefinita, comandi come java
, javac
e così via useranno le versioni appropriate delle librerie di runtime.
Molto raramente, è necessario sovrascrivere il normale comportamento del runtime Java utilizzando una versione alternativa di una classe nelle librerie standard. Ad esempio, nelle librerie di runtime potresti incontrare un bug "show stopper" che non è possibile aggirare in modo normale. In tale situazione, è possibile creare un file JAR contenente la classe modificata e quindi aggiungerlo al percorso di classe bootstrap che avvia la JVM.
Il comando java
fornisce le seguenti opzioni -X
per la modifica del percorso di classe bootstrap:
-
-Xbootclasspath:<path>
sostituisce il percorso di classe di avvio corrente con il percorso fornito. -
-Xbootclasspath/a:<path>
aggiunge il percorso fornito al percorso di classe di avvio corrente. -
-Xbootclasspath/p:<path>
antepone il percorso fornito al percorso di classe di avvio corrente.
Si noti che quando si usano le opzioni bootclasspath per sostituire o sovrascrivere una classe Java (eccetera), si sta tecnicamente modificando Java. Potrebbero esserci implicazioni di licenza se poi distribuisci il tuo codice. (Fare riferimento ai termini e alle condizioni della licenza binaria Java ... e consultare un avvocato.)