Hva betyr "Kunne ikke finne eller laste inn hovedklassen"?

Et vanlig problem som nye Java-utviklere opplever er at programmene deres ikke kjører med feilmeldingen: Kunne ikke finne eller laste inn hovedklassen ...

Hva betyr dette, hva forårsaker det, og hvordan skal du fikse det?

Løsning

Syntaksen for java-kommandoen

Først og fremst må du forstå den riktige måten å starte et program ved hjelp av kommandoen java (eller javaw). Den normale syntaksen1 er denne:

    java [  ... ]  [ ...]

der er et kommandolinjealternativ (som begynner med et "-" tegn), er et fullt kvalifisert Java-klassenavn, og `` er et vilkårlig kommandolinjeargument som sendes til programmet.
1 - Det er en annen syntaks for "kjørbare" JAR-filer som jeg vil beskrive nederst. Det fullt kvalifiserte navnet (FQN) for klassen er konvensjonelt skrevet som du ville gjort i Java-kildekode; f.eks.

    packagename.packagename2.packagename3.ClassName

Noen versjoner av java-kommandoen lar deg imidlertid bruke skråstreker i stedet for punktum; f.eks.

    packagename/packagename2/packagename3/ClassName

som (til forveksling) ser ut som et filstinavn, men ikke er det. Merk at begrepet fullstendig kvalifisert navn er standard Java-terminologi ... ikke noe jeg bare har funnet på for å forvirre deg :-) Her er et eksempel på hvordan en java-kommando skal se ut:

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

Ovennevnte kommer til å føre til at java-kommandoen gjør følgende:

  1. Søk etter den kompilerte versjonen av klassen com.acme.example.ListUsers.
  2. Last inn klassen.
  3. Kontroller at klassen har en main-metode med signature, return type og modifiers gitt ved public static void main(String[]). (Merk at navnet på metodeargumentet ikke er en del av signaturen).
  4. Kall den metoden og gi den kommandolinjeargumentene ("fred", "joe", "bert") som en String[]. Årsaker til at Java ikke finner klassen

    Når du får meldingen "Could not find or load main class ...&quot, betyr det at det første trinnet har mislyktes. Kommandoen java var ikke i stand til å finne klassen. Og faktisk vil "..." i meldingen være det fullt kvalifiserte klassenavnet som java leter etter. Så hvorfor kan det være ute av stand til å finne klassen?
    Årsak nr. 1 - du gjorde en feil med argumentet classname

    Den første sannsynlige årsaken er at du kan ha oppgitt feil klassenavn. (Eller ... riktig klassenavn, men i feil form.) Med tanke på eksemplet ovenfor er det en rekke feil måter å angi klassenavnet på:

  • Eksempel nr. 1 - et enkelt klassenavn:

    java ListUser

    Når klassen er deklarert i en pakke som com.acme.example, må du bruke hele klassenavnet inkludert pakkenavnet i java-kommandoen; f.eks. java com.acme.eksempel.ListUser

  • Eksempel 2 - et filnavn eller banenavn i stedet for et klassenavn: java ListUser.class java com/acme/eksempel/ListUser.class

  • Eksempel nr. 3 - et klassenavn med feil innkapsling: java com.acme.example.listuser

  • Eksempel nr. 4 - en skrivefeil java com.acme.eksempel.mistuser

  • Eksempel nr. 5 - et kildefilnavn java ListUser.java

  • Eksempel nr. 6 - du har glemt hele klassenavnet java mange argumenter Årsak nr. 2 - applikasjonens klassesti er feil spesifisert

    Den andre sannsynlige årsaken er at klassenavnet er riktig, men at kommandoen java ikke finner klassen. For å forstå dette må du forstå konseptet med "classpath". Dette forklares godt av Oracle-dokumentasjonen:

  • The java kommando dokumentasjon

  • Stille inn klassestien.

  • Java-veiledningen - PATH and CLASSPATH Så ... hvis du har spesifisert klassenavnet riktig, er det neste du må sjekke at du har spesifisert klassestien riktig:

  1. Les de tre dokumentene det er lenket til ovenfor. (Ja ... LES dem. Det er viktig at en Java-programmerer forstår i det minste det grunnleggende om hvordan Java classpath-mekanismene fungerer).
  2. Se på kommandolinjen og / eller miljøvariabelen CLASSPATH som er i kraft når du kjører kommandoen java. Kontroller at katalognavnene og JAR-filnavnene er korrekte.
  3. Hvis det er relative banenavn i klassestien, må du kontrollere at de løses riktig ... fra den gjeldende katalogen som er i kraft når du kjører kommandoen java.
  4. Kontroller at klassen (nevnt i feilmeldingen) kan lokaliseres på den effektive klassestien.
  5. Merk at syntaksen for klassestien er forskjellig for Windows og Linux og Mac OS. (Skilletegn for klassesti er ; på Windows og : på de andre. Hvis du bruker feil skilletegn for din plattform, vil du ikke få en eksplisitt feilmelding. I stedet vil du få en ikke-eksisterende fil eller katalog på banen som vil bli ignorert). Årsak #2a - feil katalog er på klassestien

    Når du legger en katalog på klassestien, tilsvarer den teoretisk sett roten til det kvalifiserte navnerommet. Klasser er plassert i katalogstrukturen under denne roten, ved å tilordne det fullt kvalifiserte navnet til et banenavn. Så for eksempel, hvis "/usr/local/acme/classes" er på klassebanen, så når JVM ser etter en klasse som heter com.acme.example.Foon, vil den se etter en ".class" fil med dette banenavnet:

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

Hvis du hadde satt "/usr/local/acme/classes/com/acme/example" på klassestien, ville JVM ikke kunne finne klassen. Årsak #2b - underkatalog banen ikke samsvarer med FQN

Hvis klassens FQN er "com.acme.example.Foon", vil JVM-en lete etter "Foon.class" i katalogen "com/acme/example":

  • Hvis katalogstrukturen din ikke samsvarer med pakkenavnet i henhold til mønsteret ovenfor, vil ikke JVM-en finne klassen din.
  • Hvis du prøver å omdøpe en klasse ved å flytte den, vil det også mislykkes ... men unntaksstakken vil være annerledes. Det er sannsynlig å si noe som dette: Forårsaket av: java.lang.NoClassDefFoundError: <path> (feil navn: ) fordi FQN i klassefilen ikke samsvarer med det klasselasteren forventer å finne. For å gi et konkret eksempel, antar at:
  • du ønsker å kjøre com.acme.example.Foon klassen,
  • den fullstendige filbanen er /usr/local/acme/classes/com/acme/example/Foon.class,
  • din nåværende arbeidskatalog er /usr/local/acme/classes/com/acme/example/, deretter:
# 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

Merknader:

  • Alternativet -classpath kan forkortes til -cp i de fleste Java-versjoner. Sjekk de respektive manuelle oppføringene for java, javac og så videre.

  • Tenk deg nøye om når du velger mellom absolutte og relative banenavn i klassestier. Husk at et relativt banenavn kan gå i stykker hvis den aktuelle katalogen endres.
    Årsak nr. 2c - avhengigheter som mangler i klassestien

    Klassestien må inneholde alle andre (ikke-system) klasser som applikasjonen din er avhengig av. (Systemklassene lokaliseres automatisk, og du trenger sjelden å bekymre deg for dette). For at hovedklassen skal lastes riktig, må JVM-en finne:

  • selve klassen.

  • alle klasser og grensesnitt i superklassehierarkiet (se f.eks. https://stackoverflow.com/questions/42880748).

  • alle klasser og grensesnitt som det refereres til ved hjelp av variabel- eller variabeldeklarasjoner, eller metodeanrop eller felttilgangsuttrykk. (Merk: JLS- og JVM-spesifikasjonene gir et visst rom for at en JVM kan laste klasser "lat", og dette kan påvirke når et classloader-unntak kastes). Årsak #3 - klassen har blitt erklært i feil pakken

    Det hender av og til at noen legger en kildekodefil inn i feil mappe i kildekodetreet sitt, eller de utelater pakke-deklarasjonen. Hvis du gjør dette i en IDE, vil IDE&# 39s kompilator fortelle deg om dette umiddelbart. Tilsvarende hvis du bruker et anstendig Java-byggeverktøy, vil verktøyet kjøre javac på en måte som vil oppdage problemet. Men hvis du bygger Java-koden din for hånd, kan du gjøre det på en slik måte at kompilatoren ikke merker problemet, og den resulterende .class-filen ikke er på det stedet du forventer at den skal være. Finner du fortsatt ikke problemet?

    Det er mange ting å sjekke, og det er lett å gå glipp av noe. Prøv å legge til -Xdiag alternativet til java kommandolinjen (som det første etter java). Det vil sende ut forskjellige ting om klasselasting, og dette kan gi deg ledetråder om hva det virkelige problemet er. Vurder også mulige problemer forårsaket av å kopiere og lime inn usynlige eller ikke-ASCII-tegn fra nettsteder, dokumenter og så videre. Og vurder "homoglyfer", der to bokstaver eller symboler ser like ut ... men ikke er det.

    Syntaksen java -jar syntaks

    Den alternative syntaksen som brukes for "kjørbare" JAR-filer er som følger:

  java [  ... ] -jar  [ ...]

f.eks.

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

I dette tilfellet angis navnet på inngangspunktsklassen (dvs. com.acme.example.ListUser) og klassestien i MANIFEST i JAR-filen.

IDE-er

En typisk Java IDE har støtte for å kjøre Java-applikasjoner i selve IDE-JVM-en eller i en underordnet JVM. Disse er generelt immune mot dette spesielle unntaket, fordi IDE-en bruker sine egne mekanismer for å konstruere kjøretidsstien, identifisere hovedklassen og opprette kommandolinjen java. Det er imidlertid fortsatt mulig for dette unntaket å oppstå, hvis du gjør ting bak ryggen til IDE. For eksempel, hvis du tidligere har satt opp en Application Launcher for Java-appen din i Eclipse, og du deretter flyttet JAR-filen som inneholder "main" -klassen til et annet sted i filsystemet uten å fortelle Eclipse , vil Eclipse uforvarende starte JVM med en feil klassesti. Kort sagt, hvis du får dette problemet i en IDE, se etter ting som foreldet IDE-tilstand, ødelagte prosjektreferanser eller ødelagte startkonfigurasjoner. Det er også mulig for en IDE å bare bli forvirret. IDE-er er enormt kompliserte programvare som består av mange samhandlende deler. Mange av disse delene tar i bruk ulike hurtigbufringsstrategier for å gjøre IDE-en som helhet responsiv. Disse kan noen ganger gå galt, og et mulig symptom er problemer når du starter applikasjoner. Hvis du mistenker at dette kan skje, er det verdt å prøve å starte IDE-en på nytt og gjenoppbygge prosjektet.

Andre referanser

Kommentarer (11)

Noen ganger har det som kan forårsake problemet ingenting å gjøre med hovedklassen, og jeg måtte finne ut dette på den harde måten. Det var et referert bibliotek som jeg flyttet, og det ga meg:

Kunne ikke finne eller laste inn hovedklassen xxx Linux

Jeg slettet bare den referansen, la den til igjen, og det fungerte fint igjen.

Kommentarer (5)

Angi først banen ved hjelp av denne kommandoen;

set path="paste the set path address"

Deretter må du laste inn programmet. Skriv "cd (mappenavn)" i den lagrede stasjonen og kompilere den. For eksempel, hvis programmet mitt er lagret på D-stasjonen, skriver du "D: " trykk enter og skriv " cd (mappenavn) ".

Kommentarer (3)