Hvad betyder "Kunne ikke finde eller indlæse hovedklassen"?
Et almindeligt problem, som nye Java-udviklere oplever, er, at deres programmer ikke kan køres med en fejlmeddelelse: Kunne ikke finde eller indlæse hovedklassen ...
Hvad betyder dette, hvad skyldes det, og hvordan skal du løse det?
1270
3
Kommandosyntaksen
java
Først og fremmest skal du forstå den korrekte måde at starte et program på ved hjælp af kommandoen
java
(ellerjavaw
). Den normale syntaks1 er denne:hvor
er en kommandolinjeindstilling (begyndende med et "-" tegn),
er et fuldt kvalificeret Java-klasses navn, og `` er et vilkårligt kommandolinjeargument, som sendes til dit program.1 - Der findes en anden syntaks for "eksekverbare" JAR-filer, som jeg vil beskrive nederst. Det fuldt kvalificerede navn (FQN) for klassen skrives konventionelt som i Java-kildekode; f.eks.
Nogle versioner af kommandoen
java
tillader dog, at du bruger skråstreger i stedet for punktum; f.eks.som (til forvirring) ligner et filpatnavn, men som ikke er et. Bemærk, at udtrykket fuldt kvalificeret navn er standard Java-terminologi ... ikke noget jeg lige har fundet på for at forvirre dig :-) Her er et eksempel på, hvordan en
java
-kommando skal se ud:Ovenstående vil få
java
-kommandoen til at gøre følgende:com.acme.example.ListUsers
.main
-metode med signatur, return type og modifikatorer givet vedpublic static void main(String[])
. (Bemærk, metodeargument's navn er IKKE en del af signaturen).Kald denne metode og giv den kommandolinjeargumenterne ("fred", "joe", "bert") som en
String[]
. Årsager til, at Java ikke kan finde klassenNår du får meddelelsen "Could not find or load main class ...", betyder det, at det første trin er mislykkedes. Kommandoen
java
var ikke i stand til at finde klassen. Og faktisk vil " ..." i meddelelsen være det fuldstændigt kvalificerede klasse-navn, somjava
leder efter. Så hvorfor kan den ikke finde klassen?Årsag #1 - du har lavet en fejl med classname-argumentet
Den første sandsynlige årsag er, at du måske har angivet det forkerte class name. (Eller ... det rigtige class name, men i den forkerte form.) I betragtning af eksemplet ovenfor er der her en række forkerte måder at angive class name på:
Eksempel #1 - et simpelt klassens navn:
Når klassen er deklareret i en pakke som f.eks.
com.acme.example
, så skal du bruge det fulde klasse-navn inklusive pakkenavnet ijava
-kommandoen; f.eks. java com.acme.example.ListUserEksempel #2 - et filnavn eller et stinavn i stedet for et klassens navn: java ListUser.class java com/acme/acme/eksempel/ListUser.class
Eksempel 3 - et klassens navn med forkert kasus: java com.acme.example.listuser
Eksempel 4 - en slåfejl java com.acme.example.mistuser
Eksempel nr. 5 - et kildefilnavn java ListUser.java
Eksempel #6 - du har helt glemt klassens navn java masser af argumenter Årsag #2 - applikation's classpath er forkert angivet
Den anden sandsynlige årsag er, at klassens navn er korrekt, men at kommandoen
java
ikke kan finde klassen. For at forstå dette er du nødt til at forstå begrebet "classpath". Dette er forklaret godt i Oracle-dokumentationen:The
java
command documentationIndstilling af classpath.
Java Tutorial - PATH og CLASSPATH Så ... hvis du har angivet klassens navn korrekt, er det næste du skal kontrollere, at du har angivet classpath korrekt:
java
. Kontroller, at mappenavnene og JAR-filnavnene er korrekte.java
.Bemærk, at classpath-syntaksen er forskellig for Windows i forhold til Linux og Mac OS. (Classpath-adskilleren er
;
på Windows og:
på de andre. Hvis du bruger den forkerte separator for din platform, får du ikke en eksplicit fejlmeddelelse. I stedet får du en ikke-eksisterende fil eller mappe på stien, som vil blive ignoreret i stilhed). Årsag #2a - den forkerte mappe er på classpathNår du placerer en mappe på classpath, svarer den teoretisk set til roden af det kvalificerede navnerum. Klasser er placeret i mappestrukturen under denne rod ved at mappe det fuldt kvalificerede navn til et vejnavn. Så hvis f.eks. "/usr/local/acme/classes" er på klassestien, så vil JVM'en, når den leder efter en klasse kaldet
com.acme.example.Foon
, lede efter en ".class" fil med dette vejnavn:Hvis du havde sat "/usr/local/acme/classes/com/acme/example" på classpath'en, ville JVM'en ikke kunne finde klassen. Årsag #2b - undermappestien passer ikke til FQN'en
Hvis FQN for din klasse er
com.acme.example.Foon
, så vil JVM'en søge efter "Foon.class" i mappen "com/acme/example":com.acme.example.Foon
,/usr/local/acme/classes/com/acme/example/Foon.class
,/usr/local/acme/classes/com/acme/example/
, så:Noter:
Indstillingen
-classpath
kan forkortes til-cp
i de fleste Java-udgaver. Se de respektive manualposter forjava
,javac
osv.Tænk dig godt om, når du vælger mellem absolutte og relative stinavne i classpaths. Husk, at et relativt vejnavn kan "bryde" hvis den aktuelle mappe ændres.
Årsag #2c - afhængigheder mangler i classpath'en
Classpath skal indeholde alle de andre (ikke-systemiske) klasser, som din applikation er afhængig af. (Systemklasserne findes automatisk, og du behøver sjældent at bekymre dig om dette). For at hovedklassen kan indlæses korrekt, skal JVM'en finde følgende:
selve klassen.
alle klasser og grænseflader i overklassens hierarki (se f.eks. https://stackoverflow.com/questions/42880748)
alle klasser og grænseflader, som der henvises til ved hjælp af variabler eller variabeldeklarationer eller udtryk for metodeopkald eller feltadgang. (Bemærk: JLS og JVM-specifikationerne giver et vist spillerum for, at en JVM kan indlæse klasser "lazily", og dette kan påvirke, hvornår en classloader-undtagelse bliver kastet). Årsag nr. 3 - klassen er blevet erklæret i den forkerte pakke
Det sker af og til, at nogen lægger en kildekodefil i den forkerte mappe i deres kildekodetræ, eller de udelader
package
-deklarationen. Hvis du gør dette i en IDE, vil IDE's compiler fortælle dig om dette med det samme. Hvis du bruger et ordentligt Java build-værktøj, vil værktøjet ligeledes kørejavac
på en sådan måde, at det opdager problemet. Men hvis du bygger din Java-kode i hånden, kan du gøre det på en sådan måde, at compileren ikke bemærker problemet, og den resulterende ".class" fil ikke ligger det sted, du forventer, at den skal være. Kan du stadig ikke finde problemet?Der er mange ting at kontrollere, og det er let at overse noget. Prøv at tilføje indstillingen
-Xdiag
tiljava
-kommandolinjen (som det første efterjava
). Den vil outputte forskellige ting om class loading, og det kan give dig fingerpeg om, hvad det egentlige problem er. Overvej også mulige problemer, der skyldes kopiering og indsættelse af usynlige eller ikke-ASCII-tegn fra websteder, dokumenter osv. Og tænk på "homoglyffer", hvor to bogstaver eller symboler ser ens ud ... men ikke er det.Syntaksen
java -jar
Den alternative syntaks, der anvendes til "eksekverbare" JAR-filer, er som følger:
f.eks.
I dette tilfælde er navnet på entry-point-klassen (dvs.
com.acme.example.ListUser
) og classpath angivet i JAR-filens MANIFEST.IDE'er
Et typisk Java-IDE har støtte til at køre Java-programmer i selve IDE JVM'en eller i en underordnet JVM. Disse er generelt immune over for denne særlige undtagelse, fordi IDE'et bruger sine egne mekanismer til at konstruere køretidsklassestien, identificere hovedklassen og oprette
java
-kommandolinjen. Det er dog stadig muligt, at denne undtagelse kan forekomme, hvis du gør ting bag IDE'ens ryg. Hvis du f.eks. tidligere har oprettet en Application Launcher for din Java-app i Eclipse, og du derefter har flyttet JAR-filen med klassen "main" til et andet sted i filsystemet uden at fortælle Eclipse det, vil Eclipse uden at vide det starte JVM'en med en forkert classpath. Kort sagt, hvis du får dette problem i et IDE, skal du tjekke for ting som forældet IDE-status, ødelagte projektreferencer eller ødelagte launcher-konfigurationer. Det er også muligt, at en IDE simpelthen bliver forvirret. IDE'er er enormt komplicerede stykker software, der består af mange interagerende dele. Mange af disse dele anvender forskellige caching-strategier for at gøre IDE'et som helhed responsivt. Disse kan nogle gange gå galt, og et muligt symptom er problemer ved start af programmer. Hvis du har mistanke om, at dette kan ske, er det værd at prøve ting lie genstarte dit IDE og genopbygge projektet.Andre referencer
Nogle gange har det, der kan være årsag til problemet, intet at gøre med hovedklassen, og det måtte jeg finde ud af på den hårde måde. Det var et refereret bibliotek, som jeg flyttede, og det gav mig den:
Jeg slettede bare den reference, tilføjede den igen, og så virkede det fint igen.
Indstil først stien ved hjælp af denne kommando;
Derefter skal du indlæse programmet. Skriv "cd (mappenavn)" i det gemte drev og kompilér det. Hvis mit program f.eks. er gemt på D-drevet, skal du skrive "D:" tryk på enter og skriv " cd (mappenavn)".