Frage Was bedeutet "Hauptklasse nicht finden oder laden"?


Ein häufiges Problem, das neue Java-Entwickler erleben, ist, dass ihre Programme mit der Fehlermeldung nicht ausgeführt werden können: Could not find or load main class ...

Was bedeutet das, was verursacht es und wie sollten Sie es beheben?


909
2017-08-07 03:02


Ursprung


Antworten:


Das java <class-name> Befehlssyntax

Zuallererst müssen Sie verstehen, wie Sie ein Programm mit Hilfe des java (oder javaw) Befehl.

Die normale Syntax1 ist das:

    java [ <option> ... ] <class-name> [<argument> ...]

woher <option> ist eine Befehlszeilenoption (beginnend mit einem "-" Zeichen), <class-name> ist ein vollständig qualifizierter Java-Klassenname und <argument> ist ein beliebiges Befehlszeilenargument, das an Ihre Anwendung übergeben wird.
1 - Es gibt eine zweite Syntax für "ausführbare" JAR-Dateien, die ich unten beschreiben werde.

Der vollständig qualifizierte Name (FQN) für die Klasse wird normalerweise wie im Java-Quellcode geschrieben. z.B.

    packagename.packagename2.packagename3.ClassName

Einige Versionen des java Befehl erlaubt Ihnen, Schrägstriche statt Punkte zu verwenden; z.B.

    packagename/packagename2/packagename3/ClassName

was (zum Verwechseln) wie ein Dateipfad aussieht, aber keiner ist. Beachten Sie, dass der Begriff vollständig qualifizierter Name ist Standard-Java-Terminologie ... nicht etwas, das ich gerade erfunden habe, um dich zu verwirren :-)

Hier ist ein Beispiel dafür, was a java Der Befehl sollte folgendermaßen aussehen:

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

Das oben genannte wird die verursachen java Befehl, um Folgendes zu tun:

  1. Suchen Sie nach der kompilierten Version des com.acme.example.ListUsers Klasse.
  2. Laden Sie die Klasse.
  3. Überprüfe, ob die Klasse a hat main Methode mit Unterschrift, Rückgabetyp und Modifikatoren gegeben von public static void main(String[]). (Hinweis: Der Name des Methodenarguments lautet NICHT Teil der Unterschrift.)
  4. Rufen Sie diese Methode auf und übergeben Sie ihr die Befehlszeilenargumente ("fred", "joe", "bert") als a String[].

Gründe, warum Java die Klasse nicht finden kann

Wenn Sie die Meldung "Hauptklasse nicht finden oder laden ..." erhalten, bedeutet dies, dass der erste Schritt fehlgeschlagen ist. Das java Der Befehl konnte die Klasse nicht finden. Und tatsächlich wird das "..." in der Nachricht das sein vollständig qualifizierter Klassenname Das java schaut nach.

Warum könnte es die Klasse nicht finden?

Grund # 1 - Sie haben einen Fehler mit dem Argument classname gemacht

Die erste wahrscheinliche Ursache ist, dass Sie möglicherweise den falschen Klassennamen angegeben haben. (Oder ... der richtige Klassenname, aber in der falschen Form.) Betrachtet man das obige Beispiel, hier eine Auswahl von falsche Wege um den Klassennamen anzugeben:

  • Beispiel # 1 - ein einfacher Klassenname:

    java ListUser
    

    Wenn die Klasse in einem Paket wie z com.acme.example, dann müssen Sie den vollständigen Klassennamen verwenden einschließlich der Paketname in der java Befehl; z.B.

    java com.acme.example.ListUser
    
  • Beispiel # 2 - ein Dateiname oder Pfadname anstelle eines Klassennamens:

    java ListUser.class
    java com/acme/example/ListUser.class
    
  • Beispiel # 3 - ein Klassenname mit falschem Gehäuse:

    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 lots of arguments
    

Grund # 2 - der Klassenpfad der Anwendung wurde falsch angegeben

Die zweite wahrscheinliche Ursache ist, dass der Klassenname korrekt ist, aber dass der java Der Befehl kann die Klasse nicht finden. Um das zu verstehen, müssen Sie das Konzept des "Klassenpfades" verstehen. Dies wird erklärt Gut von der Oracle-Dokumentation:

Also ... wenn Sie den Klassennamen korrekt angegeben haben, müssen Sie als nächstes prüfen, ob Sie den Klassenpfad korrekt angegeben haben:

  1. Lesen Sie die drei oben verlinkten Dokumente. (Ja ... LESEN Sie sie. Es ist wichtig, dass ein Java-Programmierer versteht zumindest die Grundlagen, wie die Java-Klassenpfadmechanismen funktionieren.)
  2. Sehen Sie sich die Befehlszeile und / oder die Umgebungsvariable CLASSPATH an, die beim Ausführen von java Befehl. Überprüfen Sie, ob die Verzeichnisnamen und JAR-Dateinamen korrekt sind.
  3. Wenn es gibt relativ Pfadnamen im Klassenpfad, überprüfen Sie, ob sie korrekt aufgelöst werden ... aus dem aktuellen Verzeichnis, das beim Ausführen von java Befehl.
  4. Überprüfen Sie, ob die Klasse (in der Fehlermeldung erwähnt) auf der gefunden werden kann Wirksam Klassenpfad.
  5. Beachten Sie, dass die Klassenpfad-Syntax lautet anders für Windows im Vergleich zu Linux und Mac OS. (Das Klassenpfadtrennzeichen ist ; unter Windows und : auf den anderen.)

Grund # 2a - das falsche Verzeichnis befindet sich im Klassenpfad

Wenn Sie ein Verzeichnis auf den Klassenpfad setzen, entspricht es theoretisch dem Stamm des qualifizierten Namensraums. Klassen befinden sich in der Verzeichnisstruktur unterhalb dieses Stamms. indem Sie den vollständig qualifizierten Namen einem Pfadnamen zuordnen. Wenn zum Beispiel "/ usr / local / acme / classes" im Klassenpfad ist, dann sucht die JVM nach einer Klasse namens com.acme.example.FoonEs sucht nach einer ".class" -Datei mit diesem Pfadnamen:

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

Wenn Sie "/ usr / local / acme / classes / com / acme / example" auf den Klassenpfad gesetzt hätten, wäre die JVM nicht in der Lage, die Klasse zu finden.

Grund # 2b - der Pfad des Unterverzeichnisses stimmt nicht mit dem FQN überein

Wenn deine Klasse FQN ist com.acme.example.Foon, dann sucht die JVM im Verzeichnis "com / acme / example" nach "Foon.class":

  • Wenn Ihre Verzeichnisstruktur nicht mit der Paketbenennung gemäß dem obigen Muster übereinstimmt, findet die JVM Ihre Klasse nicht.

  • Wenn Sie es versuchen umbenennen eine Klasse, indem man sie verschiebt, das wird auch scheitern ... aber die Ausnahme stacktrace wird anders sein.

Um ein konkretes Beispiel zu geben:

  • du willst laufen com.acme.example.Foon Klasse,
  • Der vollständige Dateipfad ist /usr/local/acme/classes/com/acme/example/Foon.class,
  • Ihr aktuelles Arbeitsverzeichnis ist /usr/local/acme/classes/com/acme/example/,

dann:

# 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

Anmerkungen:

  • Das -classpath Option kann auf verkürzt werden -cp in den meisten Java-Versionen. Überprüfen Sie die entsprechenden manuellen Eingaben für java, javac und so weiter.
  • Bedenken 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 - Abhängigkeiten fehlen im Klassenpfad

Der Klassenpfad muss alle enthalten andere (Nicht-System-) Klassen, von denen Ihre Anwendung abhängt. (Die Systemklassen werden automatisch gefunden, und Sie müssen sich selten damit befassen.) Damit die Hauptklasse korrekt geladen wird, muss die JVM Folgendes finden:

(Hinweis: Die JLS- und JVM-Spezifikationen ermöglichen einigen JVM-Klassen, "lazy" -Klassen zu laden, was sich auf das Auslösen einer Klassenloader-Ausnahme auswirken kann.)

Grund # 3 - Die Klasse wurde im falschen Paket deklariert

Es kommt gelegentlich vor, dass jemand eine Quellcodedatei in den der falsche Ordner in ihrer Quellcode - Struktur, oder sie lassen die package Erklärung. Wenn Sie dies in einer IDE tun, wird Ihnen der Compiler der IDE sofort davon berichten. Wenn Sie ein anständiges Java-Build-Tool verwenden, wird das Tool ebenfalls ausgeführt javac in einer Weise, die das Problem erkennen wird. Wenn Sie jedoch Ihren Java-Code manuell erstellen, können Sie dies so tun, dass der Compiler das Problem nicht bemerkt, und die resultierende ".class" -Datei nicht an dem Ort ist, an dem Sie es erwarten.

Kann das Problem immer noch nicht finden?

Es gibt viele Dinge zu überprüfen, und es ist leicht, etwas zu verpassen. Versuchen Sie, das hinzuzufügen -Xdiag Option zum java Befehlszeile (als erstes nach java). Es wird verschiedene Dinge über das Laden von Klassen ausgegeben, und dies kann Ihnen Hinweise geben, was das eigentliche Problem ist.


Das java -jar <jar file> Syntax

Die alternative Syntax für "ausführbare" JAR-Dateien lautet wie folgt:

  java [ <option> ... ] -jar <jar-file-name> [<argument> ...]

z.B.

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

In diesem Fall ist der Name der Eingangspunktklasse (d. H. com.acme.example.ListUser) und der Klassenpfad werden im MANIFEST der JAR-Datei angegeben.


IDEs

Eine typische Java-IDE unterstützt Java-Anwendungen in der IDE-JVM selbst oder in einer untergeordneten JVM. Diese sind allgemein immun gegen diese spezielle Ausnahme, da die IDE ihre eigenen Mechanismen verwendet, um den Klassenpfad der Laufzeit zu erstellen, die Hauptklasse zu identifizieren und die java Befehlszeile.

Es ist jedoch immer noch möglich, dass diese Ausnahme auftritt, wenn Sie Dinge hinter der Rückseite der IDE tun. Wenn Sie beispielsweise zuvor einen Application Launcher für Ihre Java-App in Eclipse eingerichtet haben und anschließend die JAR-Datei mit der Klasse "main" an eine andere Stelle im Dateisystem verschoben haben ohne Eclipse zu sagen, Eclipse würde die JVM unwissentlich mit einem falschen Klassenpfad starten.

Kurz gesagt, wenn Sie dieses Problem in einer IDE haben, suchen Sie nach veralteten IDE-Zuständen, kaputten Projektreferenzen oder kaputten Launcher-Konfigurationen.

Es ist auch möglich, dass eine IDE einfach verwirrt wird. IDEs sind sehr komplizierte Softwareteile, die viele interagierende Teile enthalten. Viele dieser Teile verwenden verschiedene Caching-Strategien, um die IDE als Ganzes ansprechbar zu machen. Diese können manchmal schief gehen, und ein mögliches Symptom sind Probleme beim Starten von Anwendungen. Wenn Sie vermuten, dass dies passieren könnte, sollten Sie Ihre IDE neu starten.


Weitere Referenzen


857
2017-08-07 03:02



Wenn der Quellcode HelloWorld.java lautet, wird der kompilierte Code verwendet HelloWorld.class.

Sie erhalten diesen Fehler, wenn Sie ihn aufrufen mit:

java HelloWorld.class

Verwenden Sie stattdessen Folgendes:

java HelloWorld

186
2018-05-21 11:06



Wenn Ihre Klassen in Paketen sind, müssen Sie cd in das Hauptverzeichnis und unter Verwendung des vollständigen Namens der Klasse (packageName.MainClassName).

Beispiel:

Meine Klassen sind hier:

D:\project\com\cse\

Der vollständige Name meiner Hauptklasse lautet:

com.cse.Main

Also ich cd zurück zum Hauptverzeichnis:

D:\project

Dann gib die java Befehl:

java com.cse.Main

95
2018-03-06 03:20



Wenn sich Ihre Hauptmethode in der Klasse unter einem Paket befindet, sollten Sie sie über das hierarchische Verzeichnis ausführen.

Angenommen, es gibt eine Quellcodedatei (Main.java):

package com.test;

public class Main {

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

Um diesen Code auszuführen, solltest du ihn platzieren Main.Class im Paket wie Verzeichnis ./com/test/Main.Java. Und im Stammverzeichnis verwenden java com.test.Main.


43
2017-10-27 12:07



Wenn der gleiche Code auf einem PC funktioniert, aber den Fehler in einem anderen zeigt, ist die beste Lösung, die ich je gefunden habe, das Kompilieren wie folgt:

javac HelloWorld.java
java -cp . HelloWorld

36
2017-08-21 06:58



Es hat mir geholfen, den Klassenpfad in der Befehlszeile anzugeben, zum Beispiel:

  1. Einen neuen Ordner erstellen, C:\temp

  2. Erstelle Datei Temp.java in C:\tempmit folgender Klasse darin:

    public class Temp {
        public static void main(String args[]) {
            System.out.println(args[0]);
        }
    }
    
  3. Öffnen Sie eine Befehlszeile im Ordner C:\temp, und schreiben Sie den folgenden Befehl, um die Temp-Klasse zu kompilieren:

    javac Temp.java
    
  4. Führen Sie die kompilierte Java-Klasse aus und fügen Sie die -classpath Option, JRE wissen zu lassen, wo die Klasse zu finden ist:

    java -classpath C:\temp Temp Hello!
    

26
2017-07-02 11:11



Gemäß der Fehlermeldung ("Hauptklasse konnte nicht gefunden oder geladen werden") gibt es zwei Kategorien von Problemen:

  1. Hauptklasse konnte nicht sein gefunden
  2. Hauptklasse konnte nicht sein geladen (Dieser Fall wird in der angenommenen Antwort nicht vollständig besprochen)

Hauptklasse konnte nicht sein gefunden wenn da ist Tippfehler oder falsche Syntax im vollständig qualifizierten Klassennamen oder es existiert im angegebenen Klassenpfad nicht.

Hauptklasse konnte nicht sein geladen wann Die Klasse kann nicht initiiert werdenNormalerweise erweitert die Hauptklasse eine andere Klasse, und diese Klasse existiert nicht im angegebenen Klassenpfad.

Beispielsweise:

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

Wenn Camel-Spring nicht enthalten ist, wird dieser Fehler gemeldet.


20
2017-09-17 01:35



Manchmal hat das, was das Problem verursacht, nichts mit der Hauptklasse zu tun, und ich musste es auf die harte Tour herausfinden. Es war eine referenzierte Bibliothek, die ich bewegte, und sie gab mir:

Konnte Hauptklasse xxx Linux nicht finden oder laden

Ich habe diese Referenz gelöscht, sie erneut hinzugefügt und es hat wieder gut funktioniert.


11
2017-11-01 18:04



Ich hatte in diesem Fall einen solchen Fehler:

java -cp lib.jar com.mypackage.Main

Es funktioniert mit ; für Windows und : für Unix:

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

11
2017-09-22 07:35



Verwenden Sie diesen Befehl:

java -cp . [PACKAGE.]CLASSNAME

Beispiel: Wenn Ihr Klassenname Hello.class ist, der aus Hello.java erstellt wurde, verwenden Sie den folgenden Befehl:

java -cp . Hello

Wenn sich Ihre Datei Hello.java im Paket com.demo befindet, verwenden Sie den folgenden Befehl

java -cp . com.demo.Hello

Bei JDK 8 kommt es häufig vor, dass die Klassendatei im selben Ordner vorhanden ist, aber der java Befehl erwartet Classpath und aus diesem Grund fügen wir hinzu -cp . Nehmen Sie den aktuellen Ordner als Referenz für den Klassenpfad.


11
2018-02-23 07:51