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

Les nouveaux développeurs Java rencontrent souvent le problème suivant : leurs programmes ne s'exécutent pas et le message d'erreur suivant apparaît : Impossible de trouver ou de charger la classe principale ....

Que signifie ce message, quelle en est la cause et comment le résoudre ?

Solution

La syntaxe de la commande "java `".

Tout d'abord, vous devez comprendre la manière correcte de lancer un programme en utilisant la commande java (ou javaw). La syntaxe normale1 est la suivante :

    java [  ... ]  [ ...]

est une option de ligne de commande (commençant par un caractère "-&quot ;), est un nom de classe Java entièrement qualifié, et `` est un argument de ligne de commande arbitraire qui est passé à votre application.
1 - Il existe une deuxième syntaxe pour les fichiers JAR "executable"que je décrirai en bas de page. Le nom pleinement qualifié (FQN) de la classe s'écrit conventionnellement comme vous le feriez dans le code source Java ; par ex.

    packagename.packagename2.packagename3.ClassName

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

    packagename/packagename2/packagename3/ClassName

qui ressemble (confusément) à un nom de fichier, mais n'en est pas un. Notez que le terme nom entièrement qualifié est une terminologie Java standard... et non quelque chose que j'ai inventé pour vous embrouiller :-) Voici un exemple de ce à quoi devrait ressembler une commande java :

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

La commande java va faire ce qui suit :

  1. Rechercher la version compilée de la classe com.acme.example.ListUsers.
  2. Charger la classe.
  3. Vérifiez que la classe a une méthode main avec signature, type de retour et modificateurs donnés par public static void main(String[]). (Remarque : le nom de l'argument de la méthode ne fait PAS partie de la signature).
  4. Appelez cette méthode en lui passant les arguments de la ligne de commande ("fred&quot ;, "joe&quot ;, "bert&quot ;) sous forme de String[]. Raisons pour lesquelles Java ne peut pas trouver la classe

    Lorsque vous obtenez le message "Could not find or load main class ...&quot ;, cela signifie que la première étape a échoué. La commande java n'a pas pu trouver la classe. Et en effet, le &quot ;...&quot ; dans le message sera le nom de classe entièrement qualifié que java recherche. Alors pourquoi la commande n'est-elle pas en mesure de trouver la classe ?
    Raison #1 - vous avez fait une erreur avec l'argument classname

    La première cause probable est que vous avez peut-être fourni le mauvais nom de classe. (Ou ... le bon nom de classe, mais sous la mauvaise forme.) En considérant l'exemple ci-dessus, voici une variété de mauvaises façons de spécifier le nom de classe :

  • Exemple #1 - un nom de classe simple :

    java ListUser

    Lorsque la classe est déclarée dans un paquetage tel que com.acme.example, alors vous devez utiliser le nom complet de la classe y compris le nom du paquetage dans la commande java ; par ex. java com.acme.example.ListUser

  • Exemple n°2 - un nom de fichier ou un chemin d'accès plutôt qu'un nom de classe : java ListUser.class java com/acme/exemple/ListUser.class

  • Exemple n° 3 - un nom de classe dont la casse est incorrecte : java com.acme.example.listuser

  • Exemple n°4 - une faute de frappe java com.acme.example.mistuser

  • Exemple #5 - un nom de fichier source java ListUser.java

  • Exemple #6 - vous avez entièrement oublié le nom de la classe java beaucoup d'arguments Raison #2 - le classpath de l&#8217application est mal spécifié

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

  • [Documentation de la commande java][1]

  • [Définition du chemin de classe][2].

  • Le tutoriel Java - [PATH et CLASSPATH][3]. Donc ... si vous avez spécifié le nom de la classe correctement, la prochaine chose à vérifier est que vous avez spécifié le classpath correctement :

  1. Lisez les trois documents liés ci-dessus. (Oui ... LISEZ-les. Il est important qu'un programmeur Java comprenne au moins les bases du fonctionnement des mécanismes de classpath de Java).
  2. Regardez la ligne de commande et / ou la variable d'environnement CLASSPATH qui est en vigueur lorsque vous exécutez la commande java. Vérifiez que les noms des répertoires et des fichiers JAR sont corrects.
  3. S'il y a des noms de chemin relatifs dans le classpath, vérifiez qu'ils se résolvent correctement ... à partir du répertoire courant qui est en vigueur lorsque vous exécutez la commande java.
  4. Vérifiez que la classe (mentionnée dans le message d'erreur) peut être localisée dans le classpath effectif.
  5. Notez que la syntaxe du classpath est différente pour Windows par rapport à Linux et Mac OS. (Le séparateur de classpath est ; sur Windows et : sur les autres. Si vous utilisez le mauvais séparateur pour votre plate-forme, vous n'obtiendrez pas de message d'erreur explicite. Au lieu de cela, vous obtiendrez un fichier ou un répertoire inexistant sur le chemin qui sera silencieusement ignoré). Raison #2a - le mauvais répertoire est sur le classpath

    Lorsque vous placez un répertoire sur le classpath, il correspond théoriquement à la racine de l'espace de nom qualifié. Les classes sont localisées dans la structure de répertoires sous cette racine, en faisant correspondre le nom pleinement qualifié à un nom de chemin. Ainsi, par exemple, si "/usr/local/acme/classes&quot ; est sur le chemin des classes, alors quand la JVM cherche une classe appelée com.acme.example.Foon, elle cherchera un fichier &quot ;.class&quot ; avec ce nom de chemin :

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

Si vous aviez mis "/usr/local/acme/classes/com/acme/example&quot ; dans le classpath, alors la JVM ne pourrait pas trouver la classe. Raison #2b - le chemin du sous-répertoire ne correspond pas au FQN

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

  • Si la structure de votre répertoire ne correspond pas à la dénomination du paquetage selon le modèle ci-dessus, la JVM ne trouvera pas votre classe.
  • Si vous essayez de renommer une classe en la déplaçant, cela échouera également... mais la pile d'exceptions sera différente. Il est susceptible de dire quelque chose comme ceci : Causé par : java.lang.NoClassDefFoundError : <path> (wrong name : ) parce que le FQN du fichier de classe ne correspond pas à ce que le chargeur de classe s'attend à trouver. Pour donner un exemple concret, supposons que :
  • vous voulez exécuter la classe com.acme.example.Foon,
  • le chemin complet du fichier est /usr/local/acme/classes/com/acme/exemple/Foon.class,
  • votre répertoire de travail actuel est /usr/local/acme/classes/com/acme/exemple/, alors :
# 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

Notes :

  • L'option -classpath peut être raccourcie en -cp dans la plupart des versions de Java. Vérifiez les entrées de manuel respectives pour java, javac et ainsi de suite.

  • Réfléchissez bien lorsque vous choisissez entre les noms de chemin absolus et relatifs dans les classpaths. Rappelez-vous qu'un nom de chemin relatif peut se briser si le répertoire courant change.
    Raison #2c - dépendances manquantes dans le classpath

    Le classpath doit inclure toutes les autres classes (non système) dont dépend votre application. (Les classes système sont localisées automatiquement, et vous avez rarement besoin de vous en préoccuper). Pour que la classe principale se charge correctement, la JVM doit trouver :

  • la classe elle-même.

  • toutes les classes et interfaces dans la hiérarchie des superclasses (voir par exemple https://stackoverflow.com/questions/42880748)

  • toutes les classes et interfaces auxquelles il est fait référence au moyen de déclarations de variables ou d'expressions d'appels de méthodes ou d'accès aux champs. (Remarque : les spécifications JLS et JVM laissent une certaine marge de manœuvre à une JVM pour charger des classes de manière "paresseuse", ce qui peut avoir une incidence sur le moment où une exception de classloader est levée). Raison #3 - la classe a été déclarée dans le mauvais paquetage

    Il arrive parfois que quelqu'un place un fichier de code source dans le mauvais dossier dans son arborescence de code source, ou qu'il oublie la déclaration package. Si vous faites cela dans un IDE, le compilateur de l'IDE vous le signalera immédiatement. De même, si vous utilisez un outil de construction Java décent, l'outil exécutera javac de manière à 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 que le fichier &quot ;.class&quot ; résultant ne soit pas à l'endroit où vous l'attendez. Vous ne trouvez toujours pas le problème ?

    Il y a beaucoup de choses à vérifier, et il est facile de manquer quelque chose. Essayez d'ajouter l'option -Xdiag à la ligne de commande java (comme première chose après java). Elle affichera diverses informations sur le chargement des classes, et cela peut vous donner des indices sur la nature du problème. Pensez également aux problèmes éventuels causés par le copier-coller de caractères invisibles ou non ASCII à partir de sites Web, de documents, etc. Et n'oubliez pas les "homoglyphes", lorsque deux lettres ou symboles se ressemblent... mais ne se ressemblent pas.

    La syntaxe "java -jar `".

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

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

par exemple

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

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

IDEs

Un IDE Java classique prend en charge l'exécution d'applications Java dans la JVM de l'IDE elle-même ou dans une JVM enfant. Ces dernières sont généralement à l'abri de cette exception particulière, car l'EDI utilise ses propres mécanismes pour construire le classpath d'exécution, identifier la classe principale et créer la ligne de commande java. Cependant, il est toujours possible que cette exception se produise, si vous faites des choses derrière l'IDE. Par exemple, si vous avez précédemment configuré un lanceur d'application pour votre application Java dans Eclipse, et que vous avez ensuite déplacé le fichier JAR contenant la classe "main&quot ; vers un autre endroit du système de fichiers sans le dire à Eclipse, Eclipse lancera involontairement la JVM avec un classpath incorrect. En bref, si vous rencontrez ce problème dans un IDE, vérifiez des éléments tels qu'un état d'IDE périmé, des références de projet cassées ou des configurations de lanceur cassées. Il est également possible que l'environnement de développement intégré s'embrouille tout simplement. Les IDE sont des logiciels extrêmement compliqués comprenant de nombreuses parties en interaction. Beaucoup de ces parties adoptent diverses stratégies de mise en cache afin de rendre l'IDE dans son ensemble réactif. Ces stratégies peuvent parfois mal fonctionner, et l'un des symptômes possibles est un problème lors du lancement des applications. Si vous pensez que cela peut se produire, il vaut la peine d'essayer des choses comme redémarrer votre IDE et reconstruire le projet.

Autres références

Commentaires (11)

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

Could not find or load main class xxx Linux

J'ai simplement supprimé cette référence, je l'ai rajoutée et tout a fonctionné à nouveau.

Commentaires (5)

Définissez d'abord le chemin en utilisant cette commande ;

set path="paste the set path address"

Ensuite, vous devez charger le programme. Tapez "cd (nom du dossier)&quot ; dans le lecteur stocké et compilez-le. Par exemple, si mon programme est stocké sur le lecteur D, tapez "D:&quot ; appuyez sur Entrée et tapez "cd (nom du dossier)&quot ;.

Commentaires (3)