Un problema comune che i nuovi sviluppatori Java sperimentano è che i loro programmi non riescono a funzionare con il messaggio di errore: "Impossibile trovare o caricare la classe principale...`
Cosa significa questo, cosa lo causa e come si dovrebbe risolvere?
java <class-name>
Prima di tutto, devi capire il modo corretto di lanciare un programma usando il comando java
(o javaw
).
La sintassi normale1 è questa:
java [ <option> ... ] <class-name> [<argument> ...]
dove <option>
è un'opzione della linea di comando (che inizia con un carattere "-"), <class-name>
è un nome di classe Java pienamente qualificato, e <argument>
è un argomento arbitrario della linea di comando che viene passato alla tua applicazione.
1 - C'è una seconda sintassi per i file JAR "eseguibili" che descriverò in fondo;
Il nome pienamente qualificato (FQN) per la classe è convenzionalmente scritto come si farebbe nel codice sorgente Java; ad esempio
packagename.packagename2.packagename3.ClassName
Tuttavia alcune versioni del comando java
permettono di usare slash al posto dei punti; ad es.
packagename/packagename2/packagename3/ClassName
che (confusamente) sembra un percorso di file, ma non lo è. Notate che il termine nome completamente qualificato è terminologia Java standard ... non qualcosa che ho inventato per confondervi :-)
Ecco un esempio di come dovrebbe essere un comando java
:
java -Xmx100m com.acme.example.ListUsers fred joe bert
Quanto sopra farà sì che il comando java
faccia quanto segue:
com.acme.example.ListUsers
.main
con signature, return type e modificatori dati da public static void main(String[])
. (Nota, il nome dell'argomento del metodo è NON parte della firma).String[]
.
Motivi per cui Java non riesce a trovare la classejava
non è riuscito a trovare la classe. E infatti, il "..." nel messaggio sarà il nome della classe qualificata che java
sta cercando.
Quindi perché potrebbe non essere in grado di trovare la classe?La prima probabile causa è che tu possa aver fornito il nome della classe sbagliato. (O ... il nome giusto della classe, ma nella forma sbagliata.) Considerando l'esempio precedente, ecco una varietà di modi sbagliati per specificare il nome della classe:
Esempio #1 - un semplice nome di classe:
java ListUser
Quando la classe è dichiarata in un pacchetto come com.acme.example
, allora devi usare il nome completo della classe incluso il nome del pacchetto nel comando java
; ad esempio
java com.acme.example.ListUser
Esempio #2 - un nome di file o un percorso piuttosto che un nome di classe: java ListUser.class java com/acme/example/ListUser.class
Esempio #3 - un nome di classe con il casing errato: java com.acme.example.listuser
Esempio #4 - un errore di battitura java com.acme.example.mistuser
Esempio #5 - un nome di file sorgente java ListUser.java
La seconda probabile causa è che il nome della classe sia corretto, ma che il comando java
non riesca a trovare la classe. Per capire questo, è necessario comprendere il concetto di "classpath". Questo è spiegato bene dalla documentazione Oracle:
Il tutorial Java - PATH e CLASSPATH Quindi ... se avete specificato correttamente il nome della classe, la prossima cosa da controllare è che abbiate specificato correttamente il classpath:
java
. Controllate che i nomi delle directory e dei file JAR siano corretti.java
.;
su Windows e :
sugli altri. Se usi il separatore sbagliato per la tua piattaforma, non riceverai un messaggio di errore esplicito. Invece, otterrete un file o una directory inesistente sul percorso che verrà silenziosamente ignorato).
Motivo #2a - la directory sbagliata è nel classpathQuando mettete una directory nel classpath, essa corrisponde teoricamente alla radice dello spazio dei nomi qualificati. Le classi si trovano nella struttura di directory sotto quella radice, mappando il nome pienamente qualificato ad un percorso. Così, per esempio, se "/usr/local/acme/classes" è nel percorso della classe, allora quando la JVM cerca una classe chiamata com.acme.example.Foon
, cercherà un file ".class" con questo pathname:
/usr/local/acme/classes/com/acme/example/Foon.class
Se la tua classe FQN è com.acme.example.Foon
, allora la JVM cercherà "Foon.class" nella directory "com/acme/example":
com.acme.example.Foon
,/usr/local/acme/classes/com/acme/example/Foon.class
,/usr/local/acme/classes/com/acme/example/
,
allora:# wrong, FQN is needed
java Foon
# wrong, there is no `com/acme/example` folder in the current working directory
java com.acme.example.Foon
# wrong, similar to above
java -classpath . com.acme.example.Foon
# fine; relative classpath set
java -classpath ../../.. com.acme.example.Foon
# fine; absolute classpath set
java -classpath /usr/local/acme/classes com.acme.example.Foon
Note:
L'opzione -classpath
può essere abbreviata in -cp
nella maggior parte delle versioni di Java. Controlla le rispettive voci di manuale per java
, javac
e così via.
Il classpath deve includere tutte le altre classi (non di sistema) da cui dipende la tua applicazione. (Le classi di sistema sono localizzate automaticamente, e raramente hai bisogno di preoccupartene). Per caricare correttamente la classe principale, la JVM deve trovare:
la classe stessa.
tutte le classi e le interfacce nella gerarchia delle superclassi (per esempio, vedi https://stackoverflow.com/questions/42880748)
package
. Se lo fate in un IDE, il compilatore dell'IDE ve lo dirà immediatamente. Allo stesso modo, se si utilizza uno strumento di compilazione Java decente, lo strumento eseguirà javac
in modo da rilevare il problema. Tuttavia, se costruisci il tuo codice Java a mano, puoi farlo in modo tale che il compilatore non noti il problema, e il file ".class" risultante non è nel posto che ti aspetti che sia.
Non riesci ancora a trovare il problema?-Xdiag
alla linea di comando java
(come prima cosa dopo java
). Mostrerà varie cose sul caricamento delle classi, e questo potrebbe offrirti indizi su quale sia il vero problema.
Inoltre, considera possibili problemi causati dal copiare e incollare caratteri invisibili o non-ASCII da siti web, documenti e così via. E considerate gli "omografi", dove due lettere o simboli sembrano uguali... ma non lo sono.java -jar <jar file>
La sintassi alternativa usata per i file JAR "eseguibili" è la seguente:
java [ <option> ... ] -jar <jar-file-name> [<argument> ...]
ad es.
java -Xmx100m -jar /usr/local/acme-example/listuser.jar fred
com.acme.example.ListUser
) e il classpath sono specificati nel MANIFEST del file JAR.java
.
Tuttavia è ancora possibile che questa eccezione si verifichi, se si fanno cose alle spalle dell'IDE. Per esempio, se avete precedentemente impostato un Application Launcher per la vostra applicazione Java in Eclipse, e poi avete spostato il file JAR che contiene la classe "main" in un posto diverso nel file system senza dirlo a Eclipse, Eclipse potrebbe involontariamente lanciare la JVM con un classpath errato.
In breve, se avete questo problema in un IDE, controllate cose come lo stato stantio dell'IDE, riferimenti al progetto non funzionanti o configurazioni del lanciatore non corrette.
È anche possibile che un IDE sia semplicemente confuso. Gli IDE sono pezzi di software enormemente complicati che comprendono molte parti che interagiscono. Molte di queste parti adottano varie strategie di caching per rendere l'IDE nel suo complesso reattivo. Queste possono a volte andare male, e un possibile sintomo sono i problemi quando si lanciano le applicazioni. Se sospettate che questo possa accadere, vale la pena provare cose come riavviare l'IDE e ricostruire il progetto.A volte ciò che potrebbe causare il problema non ha nulla a che fare con la classe principale, e ho dovuto scoprirlo nel modo più difficile. Era una libreria di riferimento che ho spostato, e mi ha dato il:
Impossibile trovare o caricare la classe principale xxx Linux
Ho semplicemente cancellato quel riferimento, l'ho aggiunto di nuovo e ha funzionato di nuovo bene.
Prima imposta il percorso usando questo comando;
set path="paste the set path address"
Poi devi caricare il programma. Digita "cd (nome della cartella)" nell'unità memorizzata e compilalo. Per esempio, se il mio programma è memorizzato nell'unità D, digitate "D:" premete invio e digitate " cd (nome cartella)".