Ricerca…


introduzione

Il classpath elenca i luoghi in cui il runtime Java deve cercare classi e risorse. Il classpath viene anche utilizzato dal compilatore Java per trovare le dipendenze precedentemente compilate ed esterne.

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: -

  1. Quelli richiesti dalla piattaforma Java vengono caricati per primi, come quelli nella libreria di classi Java e le sue dipendenze.
  2. Le classi di estensione vengono caricate successivamente (cioè quelle in jre/lib/ext/ )
  3. 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.

  1. Può essere impostato utilizzando la CLASSPATH ambiente CLASSPATH :

     set CLASSPATH=...         # Windows and csh
     export CLASSPATH=...      # Unix ksh/bash
    
  2. Può essere impostato sulla riga di comando come segue

     java -classpath ...
     javac -classpath ...
    

    Si noti che l' -classpath (o -cp ) ha la precedenza sulla CLASSPATH ambiente CLASSPATH .

  3. Il percorso di classe per un file JAR eseguibile viene specificato utilizzando l'elemento Class-Path in MANIFEST.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 elemento Class-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:

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:

  1. 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.
  2. Non puoi mettere altri personaggi prima o dopo " "; es. "someFolder / .jar" non è un jolly.
  3. 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.
  4. Un carattere jolly corrisponde solo ai file JAR nella directory stessa, non nelle sue sottodirectory.
  5. 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 in MANIFEST.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:

  1. 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.

  2. Per ogni voce E nel classpath:

    • Se la voce è una directory del filesystem:
      • Risolvi RP rispetto a E per dare un AP assoluto.
      • Verifica se AP è un percorso per un file esistente.
      • Se sì, carica la classe da quel file
    • 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.

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.)



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow