Question Que signifie "Impossible de trouver ou de charger la classe principale"?


Un problème commun aux nouveaux développeurs Java est que leurs programmes ne s'exécutent pas avec le message d'erreur: Could not find or load main class ...

Qu'est-ce que cela signifie, quelles en sont les causes, et comment le réparer?


909
2017-08-07 03:02


origine


Réponses:


le java <class-name> syntaxe de commande

Tout d'abord, vous devez comprendre la bonne façon de lancer un programme en utilisant le java (ou javaw) commande.

La syntaxe normale1 est-ce:

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

<option> est une option de ligne de commande (commençant par un caractère "-"), <class-name> est un nom de classe Java complet, et <argument> est un argument de ligne de commande arbitraire qui est transmis à votre application.
1 - Il y a une seconde syntaxe pour les fichiers JAR "exécutables" que je décrirai en bas.

Le nom complet (FQN) de la classe est écrit de manière conventionnelle comme dans le code source Java; par exemple.

    packagename.packagename2.packagename3.ClassName

Cependant, certaines versions de java commande vous permet d'utiliser des barres obliques à la place des points; par exemple.

    packagename/packagename2/packagename3/ClassName

ce qui (déroutant) ressemble à un chemin d'accès au fichier, mais n'en est pas un. Notez que le terme nom complet est la terminologie Java standard ... pas quelque chose que je viens de faire pour vous embrouiller :-)

Voici un exemple de ce que java La commande devrait ressembler à:

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

Ce qui précède va provoquer la java commande de faire ce qui suit:

  1. Rechercher la version compilée du com.acme.example.ListUsers classe.
  2. Charge la classe.
  3. Vérifiez que la classe a un main méthode avec Signature, type de retour et modificateurs donné par public static void main(String[]). (Notez que le nom de l'argument de méthode est NE PAS partie de la signature.)
  4. Appelez cette méthode en lui passant les arguments de la ligne de commande ("fred", "joe", "bert") en tant que String[].

Raisons pour lesquelles Java ne peut pas trouver la classe

Lorsque vous obtenez le message "Impossible de trouver ou de charger la classe principale ...", cela signifie que la première étape a échoué. le java commande n'a pas pu trouver la classe. Et en effet, le "..." dans le message sera le nom de classe complet cette java cherche.

Alors pourquoi pourrait-il être incapable de trouver la classe?

Raison # 1 - vous avez fait une erreur avec l'argument classname

La première cause probable est que vous avez fourni le mauvais nom de classe. (Ou ... le bon nom de classe, mais sous la mauvaise forme.) Considérant l'exemple ci-dessus, voici une variété de mauvaises manières pour spécifier le nom de la classe:

  • Exemple # 1 - un nom de classe simple:

    java ListUser
    

    Lorsque la classe est déclarée dans un package tel que com.acme.example, alors vous devez utiliser le nom de classe complet comprenant le nom du paquet dans le java commander; par exemple.

    java com.acme.example.ListUser
    
  • Exemple # 2 - un nom de fichier ou un chemin d'accès plutôt qu'un nom de classe:

    java ListUser.class
    java com/acme/example/ListUser.class
    
  • Exemple # 3 - un nom de classe avec le boîtier incorrect:

    java com.acme.example.listuser
    
  • Exemple # 4 - une faute de frappe

    java com.acme.example.mistuser
    
  • Exemple # 5 - un nom de fichier source

    java ListUser.java
    
  • Exemple # 6 - vous avez complètement oublié le nom de la classe

    java lots of arguments
    

Raison # 2 - le chemin de classe de l'application est incorrectement spécifié

La deuxième cause probable est que le nom de classe est correct, mais que le java commande ne peut pas trouver la classe. Pour comprendre cela, vous devez comprendre le concept du "classpath". Ceci est expliqué bien par la documentation Oracle:

Donc ... si vous avez correctement spécifié le nom de la classe, la prochaine chose à vérifier est que vous avez correctement spécifié le chemin de classe:

  1. Lisez les trois documents liés ci-dessus. (Oui ... LISEZ-les. Il est important qu'un programmeur Java comprend au moins les bases du fonctionnement des mécanismes de classpath Java.)
  2. Regardez la ligne de commande et / ou la variable d'environnement CLASSPATH qui est en vigueur lorsque vous exécutez le java commander. Vérifiez que les noms de répertoire et les noms de fichier JAR sont corrects.
  3. S'il y a relatif chemins d'accès dans le chemin de classe, vérifiez qu'ils résolvent correctement ... à partir du répertoire actuel qui est en vigueur lorsque vous exécutez le java commander.
  4. Vérifiez que la classe (mentionnée dans le message d'erreur) peut se trouver sur le efficace classpath.
  5. Notez que la syntaxe classpath est différent pour Windows par rapport à Linux et Mac OS. (Le séparateur de classes est ; sur Windows et : sur les autres.)

Raison # 2a - le mauvais répertoire est sur le chemin de classe

Lorsque vous placez un répertoire sur le chemin de classe, il correspond théoriquement à la racine de l'espace de nom qualifié. Les classes sont situées dans la structure de répertoires sous cette racine, en mappant le nom qualifié complet à un chemin d'accès. Par exemple, si "/ usr / local / acme / classes" est sur le chemin de la classe, alors quand la JVM cherche une classe appelée com.acme.example.Foon, il cherchera un fichier ".class" avec ce chemin:

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

Si vous aviez placé "/ usr / local / acme / classes / com / acme / exemple" sur le chemin de classe, la machine virtuelle Java ne serait pas en mesure de trouver la classe.

Raison # 2b - le chemin du sous-répertoire ne correspond pas au FQN

Si vos classes FQN est com.acme.example.Foon, alors la JVM va chercher "Foon.class" dans le répertoire "com / acme / example":

  • Si la structure de votre répertoire ne correspond pas à la dénomination du paquet selon le modèle ci-dessus, la JVM ne trouvera pas votre classe.

  • Si vous tentez Renommer une classe en la déplaçant, cela échouera aussi ... mais l'exception stacktrace sera différente.

Pour donner un exemple concret, supposons que:

  • tu veux courir com.acme.example.Foon classe,
  • le chemin complet du fichier est /usr/local/acme/classes/com/acme/example/Foon.class,
  • votre répertoire de travail actuel est /usr/local/acme/classes/com/acme/example/,

puis:

# 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

Remarques:

  • le -classpath l'option peut être raccourcie à -cp dans la plupart des versions Java. Vérifiez les entrées manuelles respectives pour java, javac etc.
  • Réfléchissez bien lorsque vous choisissez entre les chemins d'accès absolus et relatifs dans les classpaths. Rappelez-vous qu'un chemin relatif peut "casser" si le répertoire courant change.

Raison n ° 2c - dépendances manquantes dans le chemin de classe

Le chemin de classe doit inclure tous les autre les classes (non-système) dont dépend votre application. (Les classes système sont localisées automatiquement et vous avez rarement besoin de vous préoccuper de cela.) Pour que la classe principale se charge correctement, la machine virtuelle Java doit trouver:

(Remarque: les spécifications JLS et JVM permettent à une machine virtuelle Java de charger des classes "paresseusement", ce qui peut avoir une incidence lorsqu'une exception classloader est levée.)

Raison # 3 - la classe a été déclarée dans le mauvais paquet

Il arrive parfois que quelqu'un place un fichier de code source dans le le mauvais dossier dans leur arbre de code source, ou ils laissent le package déclaration. Si vous faites cela dans un IDE, le compilateur de l'IDE vous en parlera immédiatement. De même, si vous utilisez un outil de construction Java décent, l'outil fonctionnera javac d'une manière qui permettra de détecter le problème. Cependant, si vous construisez votre code Java à la main, vous pouvez le faire de telle sorte que le compilateur ne remarque pas le problème, et le fichier ".class" qui en résulte ne se trouve pas à l'endroit que vous attendez.

Vous ne trouvez toujours pas le problème?

Il y a beaucoup de choses à vérifier, et il est facile de rater quelque chose. Essayez d'ajouter le -Xdiag option à la java ligne de commande (comme la première chose après java). Il générera diverses choses sur le chargement des classes, et cela peut vous donner des indices sur le vrai problème.


le java -jar <jar file> syntaxe

La syntaxe alternative utilisée pour les fichiers JAR "exécutables" est la suivante:

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

par exemple.

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

Dans ce cas, le nom de la classe de point d'entrée (c.-à-d. com.acme.example.ListUser) et le chemin de classe sont spécifiés dans le MANIFEST du fichier JAR.


IDE

Un IDE Java typique prend en charge l'exécution d'applications Java dans la JVM IDE elle-même ou dans une JVM enfant. Ceux-ci sont généralement immunisé contre cette exception particulière, car l'EDI utilise ses propres mécanismes pour construire le chemin de classe runtime, identifier la classe principale et créer le java ligne de commande.

Cependant, il est toujours possible que cette exception se produise si vous faites des choses derrière l'EDI. Par exemple, si vous avez déjà configuré un programme de lancement d'applicatifs pour votre application Java dans Eclipse, vous avez ensuite déplacé le fichier JAR contenant la classe "main" vers un emplacement différent du système de fichiers. sans dire à Eclipse, Eclipse lancerait involontairement la JVM avec un chemin de classe incorrect.

En résumé, si vous rencontrez ce problème dans un EDI, recherchez des éléments tels que l'état IDE périmé, des références de projet brisées ou des configurations de lanceur brisées.

Il est également possible qu'un EDI soit simplement confus. Les IDE sont des logiciels extrêmement complexes comprenant de nombreuses parties en interaction. Beaucoup de ces parties adoptent diverses stratégies de mise en cache afin de rendre l'EDI globalement réactif. Ceux-ci peuvent parfois aller mal, et un symptôme possible est des problèmes lors du lancement des applications. Si vous pensez que cela pourrait se produire, il vaut la peine de redémarrer votre IDE.


Autres références


857
2017-08-07 03:02



Si votre nom de code source est HelloWorld.java, votre code compilé sera HelloWorld.class.

Vous obtiendrez cette erreur si vous l'appelez en utilisant:

java HelloWorld.class

Au lieu de cela, utilisez ceci:

java HelloWorld

186
2018-05-21 11:06



Si vos cours sont dans des paquets, vous devez cd dans le répertoire principal et exécutez en utilisant le nom complet de la classe (nomPackage.MainClassName).

Exemple:

Mes cours sont ici:

D:\project\com\cse\

Le nom complet de ma classe principale est:

com.cse.Main

Donc je cd retour au répertoire principal:

D:\project

Ensuite, émettez le java commander:

java com.cse.Main

95
2018-03-06 03:20



Si votre méthode principale est dans la classe sous un package, vous devez l'exécuter sur le répertoire hiérarchique.

Supposons qu'il existe un fichier de code source (Main.java):

package com.test;

public class Main {

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

Pour exécuter ce code, vous devez placer Main.Class dans le paquet comme le répertoire ./com/test/Main.Java. Et dans l'utilisation du répertoire racine java com.test.Main.


43
2017-10-27 12:07



Quand le même code fonctionne sur un PC, mais il montre l'erreur dans un autre, la meilleure solution que j'ai jamais trouvée compile comme suit:

javac HelloWorld.java
java -cp . HelloWorld

36
2017-08-21 06:58



Ce qui m'a aidé était de spécifier le classpath sur la ligne de commande, par exemple:

  1. Créer un nouveau dossier, C:\temp

  2. Créer un fichier Temp.java dans C:\temp, avec la classe suivante:

    public class Temp {
        public static void main(String args[]) {
            System.out.println(args[0]);
        }
    }
    
  3. Ouvrez une ligne de commande dans le dossier C:\tempet écrivez la commande suivante pour compiler la classe Temp:

    javac Temp.java
    
  4. Exécutez la classe Java compilée, en ajoutant -classpath option permettant à JRE de savoir où trouver la classe:

    java -classpath C:\temp Temp Hello!
    

26
2017-07-02 11:11



Selon le message d'erreur ("Impossible de trouver ou de charger la classe principale"), il existe deux catégories de problèmes:

  1. La classe principale ne pouvait pas être a trouvé
  2. La classe principale ne pouvait pas être chargé (ce cas n'est pas complètement discuté dans la réponse acceptée)

La classe principale ne pouvait pas être a trouvé quand il y a faute de frappe ou syntaxe incorrecte dans le nom de classe complet ou ça n'existe pas dans le chemin de classe fourni.

La classe principale ne pouvait pas être chargé quand la classe ne peut pas être initiée, typiquement la classe principale étend une autre classe et cette classe n'existe pas dans le classpath fourni.

Par exemple:

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

Si le ressort camel n'est pas inclus, cette erreur sera signalée.


20
2017-09-17 01:35



Parfois, ce qui pourrait causer le problème n'a rien à voir avec la classe principale, et j'ai dû trouver cela à la dure. C'était une bibliothèque référencée que j'ai déplacée, et cela m'a donné:

Impossible de trouver ou de charger la classe principale xxx Linux

Je viens de supprimer cette référence, je l'ai encore ajoutée, et cela a bien fonctionné.


11
2017-11-01 18:04



J'ai eu une telle erreur dans ce cas:

java -cp lib.jar com.mypackage.Main

Cela fonctionne avec ; pour Windows et : pour Unix:

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

11
2017-09-22 07:35



Utilisez cette commande:

java -cp . [PACKAGE.]CLASSNAME

Exemple: Si votre nom de classe est Hello.class créé à partir de Hello.java, utilisez la commande ci-dessous:

java -cp . Hello

Si votre fichier Hello.java est dans le paquet com.demo, utilisez la commande ci-dessous

java -cp . com.demo.Hello

Avec JDK 8, il arrive souvent que le fichier de classe soit présent dans le même dossier, mais java commande attend classpath et pour cette raison, nous ajoutons -cp . prendre le dossier actuel comme référence pour classpath.


11
2018-02-23 07:51



Essayer -Xdiag.

La réponse de Steve C couvre bien les cas possibles, mais parfois pour déterminer si la classe ne pouvait pas être a trouvé ou chargé pourrait ne pas être aussi facile. Utilisation java -Xdiag (depuis JDK 7). Cela imprime une belle stacktrace qui fournit un indice à ce que le message Could not find or load main class moyen de message.

Par exemple, il peut vous diriger vers d'autres classes utilisées par la classe principale qui n'ont pas pu être trouvées et empêcher le chargement de la classe principale.


9
2017-08-24 08:13