Was bedeutet "Could not find or load main class"?
Ein häufiges Problem, mit dem neue Java-Entwickler konfrontiert werden, besteht darin, dass ihre Programme mit der Fehlermeldung nicht ausgeführt werden können: Konnte die Hauptklasse nicht finden oder laden ...
Was bedeutet das, was ist die Ursache und wie kann man das Problem beheben?
1270
3
Die Syntax des Befehls
java
Zunächst müssen Sie verstehen, wie man ein Programm mit dem Befehl
java
(oderjavaw
) korrekt startet. Die normale Syntax1 ist diese:wobei
eine Kommandozeilenoption ist (beginnend mit einem "-" Zeichen),
ein voll qualifizierter Java-Klassenname ist und `` ein beliebiges Kommandozeilenargument ist, das an Ihre Anwendung übergeben wird.1 - Es gibt eine zweite Syntax für "ausführbare" JAR-Dateien, die ich unten beschreiben werde. Der vollqualifizierte Name (FQN) für die Klasse wird üblicherweise so geschrieben, wie man es im Java-Quellcode tun würde; z.B.
Einige Versionen des
java
-Befehls erlauben jedoch die Verwendung von Schrägstrichen anstelle von Punkten, z.B.was (verwirrenderweise) wie ein Dateipfadname aussieht, aber keiner ist. Beachten Sie, dass der Begriff voll qualifizierter Name Standard-Java-Terminologie ist ... nicht etwas, das ich mir nur ausgedacht habe, um Sie zu verwirren :-) Hier ist ein Beispiel dafür, wie ein
java
-Befehl aussehen sollte:Der obige Befehl veranlasst den
java
-Befehl, folgendes zu tun:main
Methode mit Signatur, Rückgabetyp und Modifikatoren hat, die durchpublic static void main(String[])
angegeben werden. (Beachten Sie, dass der Name des Methodenarguments NICHT Teil der Signatur ist).Rufen Sie diese Methode auf und übergeben Sie ihr die Befehlszeilenargumente ("fred", "joe", "bert") als
String[]
. Gründe, warum Java die Klasse nicht finden kannWenn Sie die Meldung "Could not find or load main class ..." erhalten, bedeutet das, dass der erste Schritt fehlgeschlagen ist. Der Befehl
java
war nicht in der Lage, die Klasse zu finden. Und tatsächlich ist das "..." in der Meldung der voll qualifizierte Klassenname, nach demjava
sucht. Warum also kann die Klasse nicht gefunden werden?Grund #1 - Sie haben einen Fehler mit dem classname-Argument gemacht
Die erste wahrscheinliche Ursache ist, dass Sie den falschen Klassennamen angegeben haben. (Oder ... den richtigen Klassennamen, aber in der falschen Form.) In Anbetracht des obigen Beispiels gibt es eine Reihe von falschen Möglichkeiten, den Klassennamen anzugeben:
Beispiel #1 - ein einfacher Klassenname:
Wenn die Klasse in einem Paket wie
com.acme.example
deklariert ist, dann müssen Sie den vollständigen Klassennamen einschließlich des Paketnamens imjava
-Befehl verwenden; z.B. java com.acme.example.ListUserBeispiel #2 - ein Dateiname oder Pfadname anstelle eines Klassennamens: java ListUser.class java com/acme/example/ListUser.class
Beispiel Nr. 3 - ein Klassenname mit falscher Schreibweise: java com.acme.example.listuser
Beispiel #4 - ein Tippfehler java com.acme.example.mistuser
Beispiel #5 - ein Quelldateiname java ListUser.java
Beispiel #6 - Sie haben den Klassennamen komplett vergessen java viele Argumente Grund #2 - der Klassenpfad der Anwendung ist falsch angegeben
Die zweite wahrscheinliche Ursache ist, dass der Klassenname korrekt ist, aber der Befehl
java
die Klasse nicht finden kann. Um dies zu verstehen, müssen Sie das Konzept des "Klassenpfads" verstehen. Dies wird in der Oracle-Dokumentation gut erklärt:The
java
command documentationEinstellung des Klassenpfads.
Das Java-Tutorial - PATH und CLASSPATH Also ... wenn Sie den Klassennamen korrekt angegeben haben, müssen Sie als Nächstes prüfen, ob Sie den Klassenpfad korrekt angegeben haben:
java
ausführen. Überprüfen Sie, ob die Namen der Verzeichnisse und JAR-Dateien korrekt sind.java
-Befehls in Kraft ist.Beachten Sie, dass die Klassenpfad-Syntax für Windows unterschiedlich ist im Vergleich zu Linux und Mac OS. (Der Klassenpfad-Trenner ist
;
unter Windows und:
unter den anderen. Wenn Sie das falsche Trennzeichen für Ihre Plattform verwenden, werden Sie keine explizite Fehlermeldung erhalten. Stattdessen erhalten Sie eine nicht existierende Datei oder ein nicht existierendes Verzeichnis im Pfad, das stillschweigend ignoriert wird). Grund #2a - das falsche Verzeichnis befindet sich auf dem KlassenpfadWenn Sie ein Verzeichnis auf den Klassenpfad setzen, entspricht es fiktiv der Wurzel des qualifizierten Namensraums. Die Klassen befinden sich in der Verzeichnisstruktur unterhalb dieser Wurzel, durch Abbildung des voll qualifizierten Namens auf einen Pfadnamen. Wenn beispielsweise "/usr/local/acme/classes" im Klassenpfad liegt, sucht die JVM bei der Suche nach einer Klasse namens
com.acme.example.Foon
nach einer ".class" Datei mit diesem Pfadnamen:Wenn Sie "/usr/local/acme/classes/com/acme/example" auf den Klassenpfad gesetzt hätten, dann könnte die JVM die Klasse nicht finden. Grund #2b - der Pfad des Unterverzeichnisses stimmt nicht mit dem FQN überein
Wenn der FQN Ihrer Klasse
com.acme.example.Foon
lautet, dann sucht die JVM nach "Foon.class" im Verzeichnis "com/acme/example":/usr/local/acme/classes/com/acme/example/Foon.class
,/usr/local/acme/classes/com/acme/example/
, dann:Hinweise:
Die Option
-classpath
kann in den meisten Java-Versionen zu-cp
abgekürzt werden. Prüfen Sie die entsprechenden Handbucheinträge fürjava
,javac
und so weiter.Überlegen Sie sorgfältig, wenn Sie zwischen absoluten und relativen Pfadnamen in Klassenpfaden wählen. Denken Sie daran, dass ein relativer Pfadname "brechen" kann, wenn sich das aktuelle Verzeichnis ändert.
Grund #2c - fehlende Abhängigkeiten im Klassenpfad
Der Klassenpfad muss alle anderen (Nicht-System) Klassen enthalten, von denen Ihre Anwendung abhängt. (Die Systemklassen werden automatisch gefunden, und Sie müssen sich selten darum kümmern). Damit die Hauptklasse korrekt geladen werden kann, muss die JVM diese finden:
die Klasse selbst.
alle Klassen und Schnittstellen in der Oberklassenhierarchie (siehe z.B. https://stackoverflow.com/questions/42880748)
alle Klassen und Schnittstellen, auf die mit Hilfe von Variablen oder Variablendeklarationen, Methodenaufrufen oder Feldzugriffsausdrücken verwiesen wird. (Hinweis: Die JLS- und JVM-Spezifikationen lassen der JVM einen gewissen Spielraum, um Klassen "lazily" zu laden, und dies kann sich darauf auswirken, wann eine Classloader-Exception ausgelöst wird). Grund #3 - die Klasse wurde im falschen Paket deklariert
Es kommt gelegentlich vor, dass jemand eine Quellcodedatei in den falschen Ordner in ihrem Quellcode-Baum ablegt oder die
Paket
-Deklaration auslässt. Wenn Sie dies in einer IDE tun, wird der IDE-Compiler Sie sofort darauf hinweisen. Wenn Sie ein anständiges Java-Build-Tool verwenden, wird das Tooljavac
so ausführen, dass das Problem erkannt wird. Wenn Sie jedoch Ihren Java-Code von Hand erstellen, können Sie dies so tun, dass der Compiler das Problem nicht bemerkt und die resultierende ".class" Datei nicht an der Stelle ist, an der Sie sie erwarten. Sie können das Problem immer noch nicht finden?Es gibt viele Dinge zu überprüfen, und es ist leicht, etwas zu übersehen. Versuchen Sie, die Option
-Xdiag
in diejava
-Befehlszeile einzufügen (als erstes nachjava
). Sie gibt verschiedene Informationen über das Laden von Klassen aus, die Ihnen Hinweise auf das eigentliche Problem geben können. Ziehen Sie auch mögliche Probleme in Betracht, die durch Kopieren und Einfügen von unsichtbaren oder Nicht-ASCII-Zeichen aus Websites, Dokumenten usw. verursacht werden. Und denken Sie an "Homoglyphen", wo zwei Buchstaben oder Symbole gleich aussehen ... aber es nicht sind'.Die Syntax "java -jar `
Die alternative Syntax, die für "ausführbare" JAR-Dateien verwendet wird, lautet wie folgt:
z.B..
In diesem Fall werden der Name der Einstiegsklasse (z.B.
com.acme.example.ListUser
) und der Klassenpfad im MANIFEST der JAR-Datei angegeben.IDEs
Eine typische Java-IDE bietet Unterstützung für die Ausführung von Java-Anwendungen in der IDE-JVM selbst oder in einer untergeordneten JVM. Diese sind generell immun gegen diese spezielle Ausnahme, weil die IDE ihre eigenen Mechanismen verwendet, um den Laufzeit-Klassenpfad zu konstruieren, die Hauptklasse zu identifizieren und die
java
-Befehlszeile zu erstellen. Es ist jedoch immer noch möglich, dass diese Ausnahme auftritt, wenn Sie Dinge hinter dem Rücken der IDE tun. Wenn Sie beispielsweise zuvor einen Application Launcher für Ihre Java-Anwendung in Eclipse eingerichtet haben und dann die JAR-Datei mit der Klasse "main" an einen anderen Ort im Dateisystem verschoben haben, ohne dies Eclipse mitzuteilen, würde Eclipse unwissentlich die JVM mit einem falschen Klassenpfad starten. Kurz gesagt, wenn Sie dieses Problem in einer IDE haben, suchen Sie nach Dingen wie einem veralteten IDE-Status, fehlerhaften Projektreferenzen oder fehlerhaften Konfigurationen des Launchers. Es ist auch möglich, dass eine IDE einfach durcheinander kommt. IDE's sind äußerst komplizierte Software, die aus vielen interagierenden Teilen besteht. Viele dieser Teile verwenden verschiedene Caching-Strategien, um die IDE als Ganzes reaktionsfähig zu machen. Diese können manchmal schief gehen, und ein mögliches Symptom sind Probleme beim Starten von Anwendungen. Wenn Sie vermuten, dass dies der Fall sein könnte, lohnt es sich, die IDE neu zu starten und das Projekt neu zu erstellen.Andere Referenzen
Manchmal hat die Ursache des Problems nichts mit der Hauptklasse zu tun, und das musste ich auf die harte Tour herausfinden. Es war eine referenzierte Bibliothek, die ich verschoben habe, und es gab mir die:
Ich löschte den Verweis, fügte ihn wieder hinzu, und es funktionierte wieder.
Legen Sie zunächst den Pfad mit diesem Befehl fest;
Dann müssen Sie das Programm laden. Geben Sie "cd (Ordnername)" in das gespeicherte Laufwerk ein und kompilieren Sie es. Zum Beispiel, wenn mein Programm auf dem Laufwerk D gespeichert ist, geben Sie "D:" ein; drücken Sie die Eingabetaste und geben Sie " cd (Ordnername)" ein.