Che cosa significa "Impossibile trovare o caricare la classe principale"?


1370

Un problema comune riscontrato dai nuovi sviluppatori Java è che i loro programmi non vengono eseguiti con il messaggio di errore: Could not find or load main class ...

Che cosa significa questo, cosa lo causa e come dovresti risolverlo?


37
Si noti che questa è una domanda di "risposta automatica" che intende essere una domanda e risposta di riferimento generica per i nuovi utenti Java. Non sono riuscito a trovare domande e risposte esistenti che lo coprano adeguatamente (IMO).
Stephen C

Risposte:


1230

La java <class-name>sintassi del comando

Prima di tutto, devi capire il modo corretto di avviare un programma usando il comando java(o javaw).

La sintassi normale 1 è questa:

    java [ <options> ] <class-name> [<arg> ...]

dove <option>è un'opzione della riga di comando (che inizia con un carattere "-"), <class-name>è un nome di classe Java pienamente qualificato ed <arg>è un argomento di riga di comando arbitrario che viene passato all'applicazione.


1 - Ci sono alcune altre sintassi che sono descritte alla fine di questa risposta.

Il nome completo (FQN) per la classe è scritto in modo convenzionale come nel codice sorgente Java; per esempio

    packagename.packagename2.packagename3.ClassName

Tuttavia, alcune versioni del javacomando consentono di utilizzare le barre anziché i punti; per esempio

    packagename/packagename2/packagename3/ClassName

che (in modo confuso) assomiglia a un percorso di file, ma non lo è. Nota che il termine nome completo è terminologia Java standard ... non qualcosa che ho appena inventato per confonderti :-)

Ecco un esempio di come javadovrebbe apparire un comando:

    java -Xmx100m com.acme.example.ListUsers fred joe bert

Quanto sopra causerà il javacomando di eseguire le seguenti operazioni:

  1. Cerca la versione compilata della com.acme.example.ListUsersclasse.
  2. Carica la classe.
  3. Verifica che la classe abbia un mainmetodo con firma , tipo restituito e modificatori forniti da public static void main(String[]). (Nota, il nome dell'argomento del metodo NON fa parte della firma.)
  4. Chiamare quel metodo passando gli argomenti della riga di comando ("fred", "joe", "bert") come a String[].

Ragioni per cui Java non riesce a trovare la classe

Quando viene visualizzato il messaggio "Impossibile trovare o caricare la classe principale ...", significa che il primo passaggio non è riuscito. Il javacomando non è stato in grado di trovare la classe. E in effetti, il "..." nel messaggio sarà il nome di classe completo che javasta cercando.

Quindi perché potrebbe non essere in grado di trovare la classe?

Motivo n. 1: hai commesso un errore con l'argomento classname

La prima causa probabile è che potresti aver fornito il nome della classe errato. (O ... il nome della classe giusto, ma nella forma sbagliata.) Considerando l'esempio sopra, ecco una varietà di modi sbagliati per specificare il nome della classe:

  • Esempio n. 1: un semplice nome di classe:

    java ListUser

    Quando la classe viene dichiarata in un pacchetto come com.acme.example, allora è necessario utilizzare il nome completo della classe incluso il nome del pacchetto nel javacomando; per esempio

    java com.acme.example.ListUser
  • Esempio n. 2 - un nome file o nome percorso anziché un nome classe:

    java ListUser.class
    java com/acme/example/ListUser.class
    
  • Esempio n. 3 - un nome di classe con il case non corretto:

    java com.acme.example.listuser
  • Esempio n. 4: un errore di battitura

    java com.acme.example.mistuser
  • Esempio n. 5 - un nome file sorgente (tranne Java 11 o successivo; vedi sotto)

    java ListUser.java
  • Esempio n. 6: hai dimenticato del tutto il nome della classe

    java lots of arguments

Motivo n. 2: il percorso di classe dell'applicazione non è stato specificato correttamente

La seconda causa probabile è che il nome della classe sia corretto, ma che il javacomando non riesca a trovare la classe. Per capirlo, devi capire il concetto di "percorso di classe". Questo è spiegato bene dalla documentazione Oracle:

Quindi ... se hai specificato correttamente il nome della classe, la prossima cosa da verificare è che hai specificato correttamente il percorso della classe:

  1. Leggi i tre documenti collegati sopra. (Sì ... LEGGili! È importante che un programmatore Java comprenda almeno le basi di come funzionano i meccanismi del percorso di classe Java.)
  2. Guarda la riga di comando e / o la variabile d'ambiente CLASSPATH che è attiva quando esegui il javacomando. Verificare che i nomi delle directory e dei file JAR siano corretti.
  3. Se nel percorso di classe sono presenti percorsi relativi , verificare che si risolvano correttamente ... dalla directory corrente che è attiva quando si esegue il javacomando.
  4. Verificare che la classe (menzionata nel messaggio di errore) possa trovarsi sul percorso di classe effettivo .
  5. Si noti che la sintassi del percorso di classe è diversa per Windows rispetto a Linux e Mac OS. (Il separatore del percorso di classe si trova ;su Windows e :sugli altri. Se si utilizza il separatore errato per la propria piattaforma, non verrà visualizzato un messaggio di errore esplicito. Invece, sul percorso verrà visualizzato un file o una directory inesistente che verrà silenziosamente ignorato .)

Motivo n. 2a: la directory errata si trova sul percorso di classe

Quando si inserisce una directory nel percorso di classe, corrisponde teoricamente alla radice dello spazio dei nomi qualificato. Le classi si trovano nella struttura della directory sotto quella radice, associando il nome completo a un nome percorso . Ad esempio, se "/ usr / local / acme / classes" si trova sul percorso della classe, quindi quando la JVM cerca una classe chiamata com.acme.example.Foon, cercherà un file ".class" con questo percorso:

  /usr/local/acme/classes/com/acme/example/Foon.class

Se avessi inserito "/ usr / local / acme / classes / com / acme / example" sul percorso della classe, la JVM non sarebbe in grado di trovare la classe.

Motivo n. 2b: il percorso della sottodirectory non corrisponde all'FQN

Se la tua classe FQN è com.acme.example.Foon, allora la JVM cercherà "Foon.class" nella directory "com / acme / example":

  • Se la struttura della directory non corrisponde alla denominazione del pacchetto secondo il modello sopra, JVM non troverà la tua classe.

  • Se si tenta di rinominare una classe spostandola, anche questo fallirà ... ma l'eccezione stacktrace sarà diversa. È possibile dire qualcosa del genere:

    Caused by: java.lang.NoClassDefFoundError: <path> (wrong name: <name>)

    perché l'FQN nel file di classe non corrisponde a ciò che il caricatore di classe si aspetta di trovare.

Per fare un esempio concreto, supponendo che:

  • vuoi fare com.acme.example.Foonlezione,
  • il percorso completo del file è /usr/local/acme/classes/com/acme/example/Foon.class,
  • la tua directory di lavoro corrente è /usr/local/acme/classes/com/acme/example/,

poi:

# 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

Appunti:

  • L' -classpathopzione può essere abbreviata -cpin molte versioni di Java. Controllare le rispettive voci manuali per java, javace così via.
  • Pensa attentamente quando scegli tra nomi di percorso assoluti e relativi nei percorsi di classe. Ricordare che un percorso relativo potrebbe "rompersi" se la directory corrente cambia.

Motivo n. 2c: dipendenze mancanti dal percorso di classe

Il percorso di classe deve includere tutte le altre classi (non di sistema) dalle quali l'applicazione dipende. (Le classi di sistema si trovano automaticamente e raramente devi preoccuparti di questo.) Per caricare correttamente la classe principale, la JVM deve trovare:

(Nota: le specifiche JLS e JVM consentono un certo ambito per una JVM per caricare le classi "pigramente", e ciò può influire quando viene generata un'eccezione del caricatore di classi.)

Motivo n. 3: la classe è stata dichiarata nel pacchetto errato

A volte capita che qualcuno inserisca un file di codice sorgente nella cartella sbagliata nella sua struttura di codice sorgente, oppure tralasci la packagedichiarazione. Se lo fai in un IDE, il compilatore dell'IDE te ne parlerà immediatamente. Allo stesso modo se si utilizza uno strumento di compilazione Java decente, lo strumento verrà eseguito javacin modo da rilevare il problema. Tuttavia, se si crea manualmente il codice Java, è possibile farlo in modo tale che il compilatore non noti il ​​problema e il file ".class" risultante non si trovi nel punto previsto.

Non riesci ancora a trovare il problema?

Ci sono molte cose da controllare ed è facile perdere qualcosa. Prova ad aggiungere l' -Xdiagopzione alla javariga di comando (come prima cosa dopo java). Produrrà varie cose sul caricamento della classe, e questo potrebbe offrire indizi su quale sia il vero problema.

Inoltre, considera i possibili problemi causati dalla copia e dall'incollaggio di caratteri invisibili o non ASCII da siti Web, documenti e così via. E considera "omogenei", dove due lettere o simboli sembrano uguali ... ma non lo sono.

Infine, apparentemente puoi riscontrare questo problema se provi ad avviarlo da un file JAR con firme errate (META-INF/*.SF).


Sintassi alternative per java

Esistono tre sintassi alternative per l'avvio dei programmi Java mediante java command.

1) La sintassi utilizzata per l'avvio di un file JAR "eseguibile" è la seguente:

  java [ <options> ] -jar <jar-file-name> [<arg> ...]

per esempio

  java -Xmx100m -jar /usr/local/acme-example/listuser.jar fred

Il nome della classe del punto di ingresso (cioè com.acme.example.ListUser) e il percorso della classe sono specificati nel MANIFEST del file JAR.

2) La sintassi per l'avvio di un'applicazione da un modulo (Java 9 e versioni successive) è la seguente:

  java [ <options> ] --module <module>[/<mainclass>] [<arg> ...]

Il nome della classe entrypoint è definito dallo <module>stesso o è dato dall'opzionale <mainclass>.

3) Da Java 11 in poi, è possibile compilare ed eseguire un singolo file di codice sorgente ed eseguirlo con la seguente sintassi:

  java [ <options> ] <sourcefile> [<arg> ...]

dove si trova (in genere) un file con il suffisso ".java".

Per maggiori dettagli, consultare la documentazione ufficiale per il javacomando per la versione Java che si sta utilizzando.


IDE

Un IDE Java tipico ha il supporto per l'esecuzione di applicazioni Java nell'IDE JVM stesso o in una JVM figlio. Questi sono generalmente immuni da questa particolare eccezione, perché l'IDE utilizza i propri meccanismi per costruire il percorso di classe di runtime, identificare la classe principale e creare la javariga di comando.

Tuttavia è ancora possibile che si verifichi questa eccezione, se si eseguono operazioni dietro l'IDE. Ad esempio, se in Eclipse in precedenza è stato impostato un Avvio applicazioni per l'app Java e quindi si è spostato il file JAR contenente la classe "principale" in una posizione diversa nel file system senza dirlo a Eclipse , Eclipse avvierebbe involontariamente la JVM con un percorso di classe errato.

In breve, se si riscontra questo problema in un IDE, verificare la presenza di elementi come lo stato IDE non aggiornato, i riferimenti di progetto non funzionanti o le configurazioni di avvio non funzionanti.

È anche possibile che un IDE venga semplicemente confuso. Gli IDE sono software estremamente complicati che comprendono molte parti interagenti. Molte di queste parti adottano varie strategie di memorizzazione nella cache per rendere l'IDE nel suo insieme reattivo. A volte questi possono andare storti e un possibile sintomo sono i problemi all'avvio delle applicazioni. Se sospetti che ciò accada, vale la pena provare altre cose come riavviare l'IDE, ricostruire il progetto e così via.


Altri riferimenti


43
Ho avuto questo problema quando stavo cercando di eseguire una classe con una libreria di terze parti. Ho invocato java in questo modo java -cp ../third-party-library.jar com.my.package.MyClass:; questo non funziona, ma è necessario aggiungere anche la cartella locale al percorso della classe (separati da :, in questo modo java -cp ../third-party-library.jar:. com.my.package.MyClass
:,

23
Dopo anni di programmazione Java sono ancora riuscito a finire su questa pagina. Per me il problema era che la sintassi del percorso di classe dipende dal sistema operativo . Sono un po 'nuovo alla programmazione su Windows e non ne avevo idea.
keyser

5
Note aggiuntive, punto 2 salvami! È triste vedere che javanon dice che non trova una classe importata, ma invece la classe principale che stai cercando di eseguire. Questo è fuorviante, anche se sono sicuro che ci sia una ragione per questo. Ho avuto il caso in cui javasapevo esattamente dove si trova la mia classe, tuttavia non è stato possibile trovare una delle classi importate. Invece di dirlo, si lamentava di non trovare la mia classe principale. Davvero fastidioso.
MSX,

Ho avuto questo problema due volte in Eclipse. La prima volta che la firma di main () era sbagliata. La seconda volta che ho rinominato un .jar, e anche se ho aggiunto quello nuovo al percorso di compilazione, Eclipse non ha trovato quello vecchio, quindi il progetto non è stato compilato, con questo errore. Ho dovuto rimuovere il file .jar da Progetto> Proprietà> Percorso build Java> Librerie.
GregT

L'ho incontrato una terza volta. Ho eseguito il programma da un file batch di Windows 10 e ho inserito il nome .jar in una variabile (chiamato con "-cp% jarname%; lib *"). Ho erroneamente messo uno spazio extra alla fine del jarname e questo ha causato l'errore. Tripletta :)
GregT

239

Se il nome del codice sorgente è HelloWorld.java, lo sarà il codice compilato HelloWorld.class.

Otterrai quell'errore se lo chiami usando:

java HelloWorld.class

Invece, usa questo:

java HelloWorld

3
Il problema è che questa soluzione funziona solo per le classi Java dichiarate nel pacchetto predefinito senza dipendenze di file JAR. (E anche allora, non sempre.) La maggior parte dei programmi Java non è così semplice.
Stephen C

1
come ha detto Stephen, questo funziona solo con "pacchetto predefinito" - il che significa che nessuna dichiarazione di pacchetto nella parte superiore del file. Per una rapida prova di alcuni codici, ho fatto: javac TestCode.javaseguito dajava TestCode
Someone Somewhere

Questo non ha funzionato per me. Dice ancora, "Impossibile trovare o caricare la classe principale HelloWorld"
Jim

java -jar HelloWorld.jar è anche un'opzione
BMaximus

12
Dovevo farlojava -classpath . HelloWorld
Chris Prince,

136

Se le classi si trovano in pacchetti, è necessario cdaccedere alla directory principale del progetto ed eseguire utilizzando il nome completo della classe (nomepacchetto.MainClassName).

Esempio:

Le mie lezioni sono qui:

D:\project\com\cse\

Il nome completo della mia classe principale è:

com.cse.Main

Quindi cdtorno alla directory del progetto di root:

D:\project

Quindi emettere il javacomando:

java com.cse.Main

Questa risposta è per salvare i programmatori Java principianti dalla frustrazione causata da un errore comune, ti consiglio di leggere la risposta accettata per una conoscenza più approfondita del percorso di classe Java.


2
Questa risposta fa un sacco di ipotesi. E ci sono altri modi per raggiungere questo obiettivo. Invece di seguire ciecamente i consigli di cui sopra, consiglierei alle persone di leggere il link nella mia risposta che spiega come funziona il percorso di classe Java. È meglio COMPRENDERE quello che stai facendo ...
Stephen C

2
Questa risposta fa le ipotesi esatte di cui avevo bisogno :) Mi trovavo nella directory del file .class e java.exe non funzionava. Una volta ho eseguito il cd-ed sopra ed eseguito con il nome del pacchetto incluso nella riga di comando ha funzionato.
Nick Constantine,

61

Se si definisce la classe principale e il metodo principale in apackage , è necessario eseguirlo sulla directory gerarchica, utilizzando il nome completo della classe ( packageName.MainClassName).

Supponiamo che esista un file di codice sorgente (Main.java):

package com.test;

public class Main {

    public static void main(String[] args) {
        System.out.println("salam 2nya\n");
    }
}

Per eseguire questo codice, è necessario inserirlo Main.Classnel pacchetto come directory ./com/test/Main.Java. E nella directory principale utilizzare java com.test.Main.


1
Vedi "Note aggiuntive n. 1" della mia risposta. Per una migliore spiegazione di questo problema.
Stephen C,

14
@StephenC Sì, la tua risposta è più completa (e ovviamente +1), ma questa particolare risposta conteneva la parola "pacchetto", che mi ha permesso di trovare velocemente ciò di cui avevo bisogno. E ha funzionato. Quindi +1 Razavi. StephenC, il tuo non ha il semplice esempio di pacchetto di cui avevo bisogno poiché sono nuovo di Java.
kmort

5
Questo era esattamente il mio problema. Ho sfogliato tonnellate di documenti Java e questo esempio concreto è ciò di cui avevo bisogno
John

1
Sì, un esempio concreto è bello, ha funzionato perfettamente. Sono sicuro che la risposta principale sia molto approfondita, ma era difficile vedere l'albero per la foresta. Nice one @Razavi
Pixel

1
Mi piace questa risposta più breve e utile anziché accettata!
Spara,

46

Quando lo stesso codice funziona su un PC, ma mostra l'errore in un altro, la soluzione migliore che abbia mai trovato è la compilazione come la seguente:

javac HelloWorld.java
java -cp . HelloWorld

2
Questa non è una buona raccomandazione. Dipende dal fatto che la variabile di ambiente CLASSPATH non sia impostata o abbia un valore coerente con ".". Sì, funziona in molti casi, ma non in altri.
Stephen C,

Beh, sicuramente javac -classpath . HelloWorld.javaavrebbe funzionato! E questa è una soluzione migliore nel tuo caso.
Stephen C,

2
Se hai il 'pacchetto com.some.address' come prima riga, questo non funzionerà. Dovrai commentare "indirizzo del pacchetto".
Joe

1
@Joe - Questo hack (commentando il pacchetto) funzionerà (in alcuni casi) ma è una cattiva idea. Un'idea migliore è apprendere / comprendere cosa ha causato il problema e implementare la soluzione corretta.
Stephen C,

36

Ciò che mi ha aiutato è stato specificare il percorso di classe sulla riga di comando, ad esempio:

  1. Crea una nuova cartella, C:\temp

  2. Crea il file Temp.java in C:\temp, con la seguente classe al suo interno:

    public class Temp {
        public static void main(String args[]) {
            System.out.println(args[0]);
        }
    }
  3. Aprire una riga di comando nella cartella C:\tempe scrivere il comando seguente per compilare la classe Temp:

    javac Temp.java
  4. Esegui la classe Java compilata, aggiungendo l' -classpathopzione per far sapere a JRE dove trovare la classe:

    java -classpath C:\temp Temp Hello!

3
In Ubuntu, ho anche dovuto specificare il percorso. Non capisco perché non può utilizzare la Directory di lavoro corrente per impostazione predefinita. Sono convinto che Java sia sponsorizzato dai produttori di tastiere !!
andato il

1
@gone - Il motivo per cui "." non è in $ PATH per impostazione predefinita è che è una trappola di sicurezza. seas.upenn.edu/cets/answers/dot-path.html
Stephen C

Grazie mille per questo ...... anche se non sono sicuro del perché java non sia stato in grado di scoprire il percorso di classe anche dopo averlo impostato nelle variabili di ambiente.
Akash89

@ akash89 - I motivi più probabili sono stati: 1) javanon stava guardando $ CLASSPATH (perché hai usato -classpath o -jar) o 2) l'impostazione del percorso di classe non era impostata nell'ambiente che non era in vigore nel contesto che javaera correre; ad esempio perché non hai "sorgente" il file dove sono stati aggiunti i comandi setenv nella shell giusta.
Stephen C

Ho ancora errore: Impossibile trovare o caricare la classe principale Temp qualcuno potrebbe aiutare!
Stella,

27

In base al messaggio di errore ("Impossibile trovare o caricare la classe principale"), esistono due categorie di problemi:

  1. La classe principale non è stata trovata
  2. Impossibile caricare la classe principale (questo caso non è completamente discusso nella risposta accettata)

Impossibile trovare la classe principale in caso di errore di battitura o sintassi errata nel nome della classe completo o se non esiste nel percorso di classe fornito .

La classe principale non può essere caricata quando la classe non può essere avviata , in genere la classe principale estende un'altra classe e quella classe non esiste nel percorso di classe fornito.

Per esempio:

public class YourMain extends org.apache.camel.spring.Main

Se la molla a cammello non è inclusa, verrà segnalato questo errore.


"Fondamentalmente" ci sono anche molte altre categorie. E il problema della superclasse mancante è un sottostacco molto insolito. (Così insolito che non l'ho mai visto ... nelle domande poste su questo sito.)
Stephen C,

Ci sono DUE perché l'errore dice "Impossibile trovare o caricare la classe principale". Se ci sono altre categorie, per favore avvisami. L'ho visto, quindi voglio solo condividerlo qui forse qualcun altro ne avrà bisogno.
Xiao Peng - ZenUML.com,

1
Lo avrei modificato in qualcosa del tipo "Devi includere tutte le classi necessarie per avviare la classe principale per evitare questo particolare errore". Non sto cercando di convincerti. È solo un modo che vorrei vedere. Ho lasciato la risposta qui solo per le persone a cui potrebbe piacere leggere le cose in questo modo. Non estendiamo ulteriormente questa discussione :) Ho cambiato la mia affermazione in "non completamente discussa nella risposta accettata" e spero che ti senta meglio.
Xiao Peng - ZenUML.com,

5
Questa informazione è cruciale e merita una menzione esplicita (questa è l'unica risposta che menziona extends). Ho appena imparato a mie spese che quando la classe principale non riesce a caricarsi perché ne estende un'altra che non è stata trovata , java non segnala quale classe effettiva non è stata trovata (a differenza NoClassDefFoundError). Quindi sì, succede, ed è una situazione da capogiro quando non lo sai.
Hugues M.

1
In questa situazione c'è un modo per dire esattamente quale classe di dipendenza non riesce a caricare?
Carlos A. Ibarra,

16

Ho avuto un errore del genere in questo caso:

java -cp lib.jar com.mypackage.Main

Funziona con ;Windows e :Unix:

java -cp lib.jar; com.mypackage.Main

Sì. Questo è molto probabilmente perché il tuo Mainnon è nel file JAR. -cp lib.jar;indica la stessa cosa, ad -cp lib.jar;. esempio, la directory corrente è inclusa nel percorso di classe.
Stephen C,

Finalmente risolto il problema per unix .. grazie (funziona con :)
Vicky

16

Prova -Xdiag .

La risposta di Steve C copre bene i possibili casi, ma a volte determinare se la classe non può essere trovata o caricata potrebbe non essere così facile. Utilizzare java -Xdiag(dal JDK 7). Questo stampa una bella traccia stack che fornisce un suggerimento sul Could not find or load main classsignificato del messaggio.

Ad esempio, può indicare altre classi utilizzate dalla classe principale che non sono state trovate e che hanno impedito il caricamento della classe principale.


16

Usa questo comando:

java -cp . [PACKAGE.]CLASSNAME

Esempio: se il tuo nome di classe è Hello.class creato da Hello.java, utilizza il comando seguente:

java -cp . Hello

Se il tuo file Hello.java si trova nel pacchetto com.demo, usa il comando seguente

java -cp . com.demo.Hello

Con JDK 8 molte volte accade che il file di classe sia presente nella stessa cartella, ma il javacomando prevede il percorso di classe e per questo motivo aggiungiamo -cp .di prendere la cartella corrente come riferimento per il percorso di classe.


Funziona solo in casi semplici. I casi più complicati richiedono un percorso di classe più complicato.
Stephen C,

E per >> davvero << casi semplici, -cp .non è necessario, perché se $CLASSPATHnon è impostato, allora .è il percorso di classe predefinito.
Stephen C

No Stephen, molte volte nel percorso di classe predefinito di Windows non funziona. L'ho provato su tre macchine diverse, puoi provarlo anche tu.
shaILU

Questo probabilmente perché hai effettivamente impostato la variabile d'ambiente% CLASSPATH% da qualche parte. Se lo fai, allora non stai usando il percorso di classe predefinito. (Cosa genera l' echo %CLASSPATH%output?) E no, non riesco a controllare perché non ho un PC Windows.
Stephen C,

2
Questo ha funzionato per me quando ho provato a eseguire un semplice programma dalla riga di comando
SnuKies,

15

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:

Impossibile trovare o caricare la classe principale xxx Linux

Ho appena eliminato quel riferimento, l'ho aggiunto di nuovo e ha funzionato di nuovo bene.


1
Sembra che il problema fosse che avevi un percorso di classe errato a causa di un "riferimento" interrotto nel tuo progetto nell'IDE. Aggiornerò la mia risposta per coprire quel caso.
Stephen C,

@StephenC e EduardoDennis, era anche qui che mancava un vaso, quel vaso conteneva un'interfaccia su cui la classe principale dipendeva per essere istanziata. Quindi, il messaggio di errore è troppo ampio. Dovrei dire "impossibile trovare" se il file di classe non viene trovato e "impossibile caricare (dipendenze mancanti)" se manca qualcos'altro ma non il file stesso, quindi il messaggio di errore essendo troppo ampio è fuorviante se si focalizza solo nella parte "trova" :(
Aquarius Power il

@AquariusPower - Dovrebbe esserci stata un'ulteriore "causata da" stacktrace per l'eccezione "causa" che diceva che mancava la classe. Se vuoi suggerire agli sviluppatori Java che cambiano un messaggio di errore che dice che da oltre 20 anni ... sentiti libero. (Penso che il messaggio di errore sia corretto. Il problema era che >> tu << hai ristretto la clausola sbagliata.)
Stephen C

@StephenC quello che volevo dire è che hanno sicuramente accesso alle informazioni se il file della classe principale è disponibile o meno, quindi perché non mostrarci un messaggio di errore migliore che dice che tale file è mancante. D'altra parte, potrebbero anche dire "Il file è stato trovato ma non è stato possibile caricarlo" a quel punto, ci concentreremo prontamente sulle dipendenze invece di perdere mezza giornata a cercare e testare cose da capire. Solo che intendevo :). Possono farlo in modo limitato per oltre 20 anni, ma possono migliorarlo e siamo qui per garantire che ciò accadrà attraverso le nostre critiche e lamentele! : D
Aquarius Power l'

Per favore, capisci cosa intendevo >> I <<. Lamentarsi in qualche oscuro commento su domande e risposte di 3 anni non otterrà nulla. Le persone che potrebbero concettualmente agire sulle tue lamentele non se ne accorgeranno. Se vuoi fare qualcosa di costruttivo, invia una patch. (Non valuto le tue possibilità, ma saranno maggiori che se ti piacesse solo per questo.)
Stephen C

10

In questo caso hai:

Impossibile trovare o caricare la classe principale ? Classpath

È perché stai usando "-classpath", ma il trattino non è lo stesso trattino usato dal javaprompt dei comandi. Ho avuto questo problema copiando e incollando da Blocco note a cmd.


2
Wow! Questa è una causa totalmente bizzarra! (Ma ti serve per usare Notepad invece di un vero editor di testo :-))
Stephen C

10

Ho avuto lo stesso problema e finalmente ho trovato il mio errore :) Ho usato questo comando per la compilazione e ha funzionato correttamente:

javac -cp "/home/omidmohebbi/AAAATest/jars/core-1.7.jar:/home/omidmohebbi/AAAATest/jars/javase-1.7.jar:/home/omidmohebbi/AAAATest/jars/qrgen-1.2.jar" qrcode.java

Ma questo comando non ha funzionato per me (non sono riuscito a trovare o caricare la classe principale qrcode):

java -cp "/home/omidmohebbi/AAAATest/jars/core-1.7.jar:/home/omidmohebbi/AAAATest/jars/javase-1.7.jar:/home/omidmohebbi/AAAATest/jars/qrgen-1.2.jar" qrcode

Alla fine ho appena aggiunto il carattere ':' alla fine del percorso di classe e il problema è stato risolto:

java -cp "/home/omidmohebbi/AAAATest/jars/core-1.7.jar:/home/omidmohebbi/AAAATest/jars/javase-1.7.jar:/home/omidmohebbi/AAAATest/jars/qrgen-1.2.jar:" qrcode

7

Nel mio caso, è apparso un errore perché avevo fornito il nome del file di origine anziché il nome della classe.

Dobbiamo fornire il nome della classe contenente il metodo principale all'interprete.


Sì. Vedi il mio esempio n. 2 dei modi sbagliati per specificare il nome della classe !!
Stephen C,

7

Questo potrebbe aiutarti se il tuo caso è specificamente simile al mio: come principiante ho anche riscontrato questo problema quando ho provato a eseguire un programma Java.

L'ho compilato in questo modo:

javac HelloWorld.java

E ho provato a correre anche con la stessa estensione:

java Helloworld.java

Quando ho rimosso il .javae riscritto il comando come java HelloWorld, il programma ha funzionato perfettamente. :)


2
Questo perché stai eseguendo la versione compilata del tuo .java. In realtà sta eseguendo il file .class
Jason V,

Per la cronaca, questo è lo stesso del motivo n. 1, esempio n. 5 nella mia risposta ...
Stephen C

6

Sembra che tutte le risposte qui siano dirette agli utenti Windows. Per Mac, il separatore del percorso di classe è :no ;. Poiché non viene generato un errore durante l'impostazione del percorso di classe, ;questo può essere difficile da scoprire se proviene da Windows a Mac.

Ecco il comando Mac corrispondente:

java -classpath ".:./lib/*" com.test.MyClass

Dove in questo esempio si trova il pacchetto com.teste una libcartella deve essere inclusa nel percorso di classe.


2
Su Linux come su Mac.
Alex78191,

Perché /*è necessario
Alex78191,

È una sintassi jolly. (Non è obbligatorio. Puoi elencare esplicitamente i JAR se vuoi.)
Stephen C,

6

inserisci qui la descrizione dell'immagine

Posizione del file di classe: C: \ test \ com \ company

Nome file: Main.class

Nome di classe completo : com.company.Main

Comando da riga di comando:

java  -classpath "C:\test" com.company.Main

Nota qui che il percorso della classe NON include \ com \ company


6

Ho trascorso una discreta quantità di tempo cercando di risolvere questo problema. Ho pensato che in qualche modo stavo impostando il mio classpath in modo errato, ma il problema era che ho digitato:

java -cp C:/java/MyClasses C:/java/MyClasses/utilities/myapp/Cool  

invece di:

java -cp C:/java/MyClasses utilities/myapp/Cool   

Ho pensato che il significato di pienamente qualificato intendesse includere il nome completo del percorso anziché il nome completo del pacchetto.


Ho aggiornato la mia risposta per cercare di affrontare quella confusione.
Stephen C,

2
Nessuno di questi è corretto. La classe deve essere data come utilities.myapp.Coolo qualunque sia il nome del suo pacchetto, se presente.
Marchese di Lorne,

5

Innanzitutto imposta il percorso usando questo comando;

set path="paste the set path address"

Quindi è necessario caricare il programma. Digitare "cd (nome cartella)" nell'unità memorizzata e compilarlo. Ad esempio, se il mio programma è stato memorizzato sull'unità D, digitare "D:" premere Invio e digitare "cd (nome cartella)".


4
Questo non aiuta. Questa domanda riguarda i programmi Java, non i normali eseguibili. Java non usa PATH per localizzare nulla, e se "cd" aiuta allora per fortuna piuttosto che per giudizio.
Stephen C,

if "cd" helps then it by luck rather than by judgement. Questo è sbagliato (credo), poiché java utilizza la directory corrente .come parte del percorso di classe per impostazione predefinita.
GKFX

2
@GKFX - Questo è ciò che intendo. A meno che non si sappia che si sta utilizzando il percorso di classe predefinito (o un percorso di classe con "." Su di esso), "cd" non avrà alcun effetto. Questa soluzione funziona più per fortuna (cioè indovinando / sperando che "." Sia sul percorso di classe) che per giudizio (cioè controllando che "." Sia sul percorso di classe). Inoltre non sei corretto riguardo l'impostazione predefinita. Java utilizza "." come percorso di classe per impostazione predefinita, non come parte del percorso di classe per impostazione predefinita.
Stephen C,

5

Ciò che risolveva il problema nel mio caso era:

Fare clic con il tasto destro sul progetto / classe che si desidera eseguire, quindi Run As-> Run Configurations. Quindi è necessario correggere la configurazione esistente o aggiungerne di nuovi nel modo seguente:

apri la Classpathscheda, fai clic sul Advanced...pulsante quindi aggiungi la bincartella del tuo progetto.


5

Se usi Maven per creare il file JAR, assicurati di specificare la classe principale nel file pom.xml:

<build>
    <plugins>
        <plugin>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>class name us.com.test.abc.MyMainClass</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</build>

4

Questo è un caso specifico, ma da quando sono arrivato a questa pagina alla ricerca di una soluzione e non l'ho trovata, la aggiungerò qui.

Windows (testato con 7) non accetta caratteri speciali (come á) in nomi di classi e pacchetti. Linux lo fa, però.

L'ho scoperto quando ho creato un .jarin NetBeans e ho provato a eseguirlo nella riga di comando. Funzionava in NetBeans ma non nella riga di comando.


4

Su Windows inserisci .;il valore CLASSPATH all'inizio.

Il . (punto) significa "cerca nella directory corrente". Questa è una soluzione permanente.

Inoltre puoi impostarlo "una volta" con set CLASSPATH=%CLASSPATH%;.. Questo durerà fino a quando la finestra cmd è aperta.


1
Questo consiglio può o meno aiutare. Aiuterà se l'albero delle classi contenente le classi nella directory corrente. Non lo sarà se non lo sono. In realtà non lo farei. Invece, creerei uno script wrapper one-liner che ha funzionato indipendentemente dal fatto che l'utente si trovi nella directory "giusta".
Stephen C,

4

Devi davvero farlo dalla srccartella. Lì si digita la seguente riga di comando:

[name of the package].[Class Name] [arguments]

Diciamo che la tua classe si chiama CommandLine.classe il codice è simile al seguente:

package com.tutorialspoint.java;

    /**
     * Created by mda21185 on 15-6-2016.
     */

    public class CommandLine {
        public static void main(String args[]){
            for(int i=0; i<args.length; i++){
                System.out.println("args[" + i + "]: " + args[i]);
            }
        }
    }

Quindi dovresti accedere cdalla cartella src e il comando che devi eseguire sarebbe simile al seguente:

java com.tutorialspoint.java.CommandLine this is a command line 200 -100

E l'output sulla riga di comando sarebbe:

args[0]: this
args[1]: is
args[2]: a
args[3]: command
args[4]: line
args[5]: 200
args[6]: -100

2
Una classe non può essere chiamata "CommandLine.class". Sarebbe un errore di sintassi Java. (Quello che vuoi dire è che il file contenente la classe compilata si chiama "CommandLine.class" ...). L'altro problema è che le tue istruzioni per "cd nella directory dei sorgenti" funzionano solo se hai compilato il codice >> nella << struttura della directory dei sorgenti. Infine, se la tua compilazione ha usato un argomento "-cp", allora hai bisogno di un equivalente su quando esegui.
Stephen C,

Nel mio progetto ho la cartella src e la cartella bin alla radice. Ho dovuto cdinserire srce quindi eseguire il comando java ../bin com.blah.blah.MyClassche ha funzionato per me. Quindi grazie per il suggerimento!
tamj0rd2,

3

In Java, quando a volte si esegue JVM dalla riga di comando utilizzando l'eseguibile java e si sta tentando di avviare un programma da un file di classe con vuoto statico pubblico principale (PSVM), è possibile che si verifichi l'errore riportato di seguito anche se il parametro classpath in la JVM è precisa e il file di classe è presente sul percorso di classe:

Error: main class not found or loaded

Ciò accade se non è stato possibile caricare il file di classe con PSVM. Una possibile ragione di ciò è che la classe potrebbe implementare un'interfaccia o estendere un'altra classe che non si trova sul percorso di classe. Normalmente se una classe non si trova sul percorso di classe, l'errore generato indica come tale. Tuttavia, se la classe in uso viene estesa o implementata, java non è in grado di caricare la classe stessa.

Riferimento: https://www.computingnotes.net/java/error-main-class-not-found-or-loaded/


1
Hai letto la risposta accettata? La tua risposta aggiunge qualcosa di nuovo?
Stephen C,

1
@StephenC Ho provato a trovare un motivo nella tua lista guardando le categorie "Motivo" e i loro punti. Non sono riuscito a trovare il punto corrispondente nel titolo "Reason # 1" e "Reason # 2" non sembrava vicino al mio caso (perché ero sicuro che non ci fossero problemi con il percorso di classe stesso). Ho trovato il motivo eseguendo esperimenti e sono rimasto sorpreso dal fatto che nel mio caso sia stato mostrato l'errore "classe principale non trovata" perché l'implementazione dell'interfaccia non era sul percorso della classe. Sicuramente puoi dire "dovresti leggere tutto quanto descritto nel post" ma mi sembra che il tuo elenco di motivi possa essere migliorato.
Gumkins,

3

Quando si esegue la javacon l' -cpopzione come pubblicizzato in Windows PowerShell è possibile ottenere un errore che sembra qualcosa di simile:

The term `ClassName` is not recognized as the name of a cmdlet, function, script ...

Affinché PowerShell accetti il ​​comando, gli argomenti -cpdell'opzione devono essere racchiusi tra virgolette come in:

java -cp 'someDependency.jar;.' ClassName

Formare il comando in questo modo dovrebbe consentire a Java di elaborare correttamente gli argomenti del percorso di classe.


3

Ho anche riscontrato errori simili durante il test di una connessione JDBC Java MongoDB. Penso che sia utile riassumere la mia soluzione finale in breve, in modo che in futuro chiunque possa esaminare direttamente i due comandi e procedere bene.

Supponiamo di essere nella directory in cui esistono il file Java e le dipendenze esterne (file JAR).

Compilare:

javac -cp mongo-java-driver-3.4.1.jar JavaMongoDBConnection.java
  • -cp - argomento classpath; passa uno per uno tutti i file JAR dipendenti
  • * .java - Questo è il file di classe Java che ha il metodo principale. sdsd

Correre:

java -cp mongo-java-driver-3.4.1.jar: JavaMongoDBConnection
  • Si prega di osservare i due punti (Unix) / virgola (Windows) dopo la fine di tutti i file JAR di dipendenza
  • Alla fine, osserva il nome della classe principale senza alcuna estensione (no .class o .java)

Tutto questo presuppone che 1) JavaMongoDBConnectionnon abbia un pacchetto e 2) non cambi directory. È, per non dire altro, fragile. E non spiegando i problemi, porterà i neofiti a provare questo approccio in situazioni in cui non funzionerà . In breve, incoraggia le "tecniche di programmazione voodoo": en.wikipedia.org/wiki/Voodoo_programming
Stephen C

3

Va bene, ci sono già molte risposte, ma nessuno ha menzionato il caso in cui le autorizzazioni ai file possono essere il colpevole.

Durante l'esecuzione, un utente potrebbe non avere accesso al file JAR o a una delle directory del percorso. Ad esempio, considera:

File Jar in /dir1/dir2/dir3/myjar.jar

L'utente1 che possiede il file JAR può fare:

# Running as User1
cd /dir1/dir2/dir3/
chmod +r myjar.jar

Ma non funziona ancora:

# Running as User2
java -cp "/dir1/dir2/dir3:/dir1/dir2/javalibs" MyProgram
Error: Could not find or load main class MyProgram

Questo perché l'utente in esecuzione (Utente2) non ha accesso a dir1, dir2 o javalibs o dir3. Potrebbe far impazzire qualcuno quando User1 può vedere i file e può accedervi, ma l'errore si verifica ancora per User2.


2

Ho avuto questo errore dopo aver fatto mvn eclipse:eclipse Questo ha incasinato .classpathun po 'il mio file.

Ho dovuto cambiare le righe .classpathda

<classpathentry kind="src" path="src/main/java" including="**/*.java"/>
<classpathentry kind="src" path="src/main/resources" excluding="**/*.java"/>

per

<classpathentry kind="src" path="src/main/java" output="target/classes" />
<classpathentry kind="src" path="src/main/resources" excluding="**"  output="target/classes" />

2

Non sono stato in grado di risolvere questo problema con le soluzioni indicate qui (sebbene la risposta dichiarata abbia senza dubbio chiarito i miei concetti). Ho affrontato questo problema due volte e ogni volta ho provato diverse soluzioni (nell'IDE Eclipse).

  • In primo luogo, mi sono imbattuto in più mainmetodi in diverse classi del mio progetto. Quindi, avevo eliminato il mainmetodo dalle classi successive.
  • In secondo luogo, ho provato la seguente soluzione:
    1. Fare clic con il tasto destro sulla directory principale del mio progetto.
    2. Vai alla fonte, quindi ripulisci e mantieni le impostazioni predefinite e su Fine. Dopo alcune attività in background verrai indirizzato alla directory principale del tuo progetto.
    3. Dopo di ciò chiudo il mio progetto, lo riapro e, boom, ho finalmente risolto il mio problema.

1
L'eliminazione dei mainmetodi non risolverà il problema. Non c'è nulla di tecnicamente sbagliato in un'applicazione con più punti di ingresso.
Stephen C,
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.