Que signifie «Impossible de trouver ou de charger la classe principale»?

1370

Un problème courant rencontré par les 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, qu'est-ce qui le provoque et comment y remédier?

Stephen C
la source
37
Veuillez noter qu'il s'agit d'une question "d'auto-réponse" qui est destinée à être un Q&A de référence générique pour les nouveaux utilisateurs Java. Je n'ai pas pu trouver un Q & A existant qui couvre cela adéquatement (OMI).
Stephen C

Réponses:

1230

La java <class-name>syntaxe de commande

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

La syntaxe normale 1 est la suivante:

    java [ <options> ] <class-name> [<arg> ...]

<option>est une option de ligne de commande (commençant par un caractère "-"), <class-name>est un nom de classe Java complet et <arg>est un argument de ligne de commande arbitraire qui est transmis à votre application.


1 - Il existe d'autres syntaxes qui sont décrites vers la fin de cette réponse.

Le nom complet (FQN) de la classe est conventionnellement écrit comme vous le feriez dans le code source Java; par exemple

    packagename.packagename2.packagename3.ClassName

Cependant, certaines versions de la javacommande vous permettent d'utiliser des barres obliques au lieu de points; par exemple

    packagename/packagename2/packagename3/ClassName

qui (confusément) ressemble à un chemin de fichier, mais n'en est pas un. Notez que le terme nom complet est une terminologie Java standard ... pas quelque chose que j'ai inventé pour vous confondre :-)

Voici un exemple de ce à quoi javadevrait ressembler une commande:

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

Ce qui précède va amener la javacommande à effectuer les opérations suivantes:

  1. Recherchez la version compilée de la com.acme.example.ListUsersclasse.
  2. Chargez la classe.
  3. Vérifiez que la classe possède une mainméthode avec signature , type de retour et modificateurs donnés par public static void main(String[]). (Remarque: le nom de l'argument de méthode NE fait PAS partie de la signature.)
  4. Appelez cette méthode en lui passant les arguments de ligne de commande ("fred", "joe", "bert") sous la forme d'un String[].

Raisons pour lesquelles Java ne trouve pas 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é. La javacommande n'a pas pu trouver la classe. Et en effet, le « ... » dans le message sera le nom complet de la classe qui javaest à la recherche.

Alors pourquoi ne pourrait-il pas trouver la classe?

Raison n ° 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.) Compte tenu de 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 package tel que com.acme.example, vous devez utiliser le nom de classe complet, y compris le nom du package dans la javacommande; 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 (sauf pour Java 11 ou version ultérieure; voir ci-dessous)

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

    java lots of arguments

Raison n ° 2 - le chemin de classe de l'application n'est pas spécifié correctement

La deuxième cause probable est que le nom de classe est correct, mais que la javacommande ne peut pas trouver la classe. Pour comprendre cela, vous devez comprendre le concept de "chemin de classe". Ceci est bien expliqué 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 comprenne au moins les bases du fonctionnement des mécanismes de chemin de classe Java.)
  2. Regardez la ligne de commande et / ou la variable d'environnement CLASSPATH qui est en vigueur lorsque vous exécutez la javacommande. Vérifiez que les noms de répertoire et les noms de fichier JAR sont corrects.
  3. S'il y a des chemins d'accès relatifs dans le chemin de classe, vérifiez qu'ils se résolvent correctement ... à partir du répertoire en cours qui est en vigueur lorsque vous exécutez la javacommande.
  4. Vérifiez que la classe (mentionnée dans le message d'erreur) peut se trouver sur le chemin de classe effectif .
  5. Notez que la syntaxe du chemin de classe est différente pour Windows par rapport à Linux et Mac OS. (Le séparateur de chemin de classe 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 n ° 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 noms qualifié. Les classes sont situées dans la structure de répertoires sous cette racine, en mappant le nom complet à un nom de chemin . Ainsi, par exemple, si "/ usr / local / acme / classes" se trouve sur le chemin d'accès aux classes, alors lorsque la machine virtuelle Java recherche une classe appelée com.acme.example.Foon, elle recherche un fichier ".class" 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" sur le chemin de classe, la JVM ne pourrait pas trouver la classe.

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

Si votre classe 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 au nom du package 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 le stacktrace d'exception sera différent. Il est susceptible de dire quelque chose comme ceci:

    Caused by: java.lang.NoClassDefFoundError: <path> (wrong name: <name>)

    car le FQN dans le fichier de classe ne correspond pas à ce que le chargeur de classe s'attend à trouver.

Pour donner un exemple concret, en supposant que:

  • vous voulez exécuter la com.acme.example.Foonclasse,
  • le chemin de fichier complet 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:

  • L' -classpathoption peut être raccourcie -cpdans la plupart des versions Java. Vérifiez les entrées manuelles respectives pour java, javacetc.
  • Réfléchissez bien lorsque vous choisissez entre les chemins absolus et relatifs dans les chemins de classe. N'oubliez pas qu'un chemin d'accès relatif peut "casser" si le répertoire en cours change.

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

Le chemin de classe 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:

(Remarque: les spécifications JLS et JVM permettent à une JVM de charger les classes "paresseusement", ce qui peut affecter le déclenchement d'une exception de chargeur de classe.)

Raison n ° 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 mauvais dossier de son arborescence de code source, ou laisse de côté la packagedéclaration. Si vous faites cela dans un IDE, le compilateur de l'IDE vous en informera immédiatement. De même, si vous utilisez un outil de génération Java décent, l'outil s'exécutera javacd'une manière qui détectera le problème. Cependant, si vous construisez votre code Java à la main, vous pouvez le faire de telle manière que le compilateur ne remarque pas le problème et que le fichier ".class" résultant 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 l' -Xdiagoption à la javaligne de commande (comme première chose après java). Il affichera diverses choses sur le chargement des classes, et cela peut vous donner des indices sur le vrai problème.

Tenez également compte des problèmes possibles causés par la copie et le collage de caractères invisibles ou non ASCII à partir de sites Web, de documents, etc. Et considérez les "homoglyphes", si deux lettres ou symboles se ressemblent ... mais ne le sont pas.

Enfin, vous pouvez apparemment rencontrer ce problème si vous essayez de lancer à partir d'un fichier JAR avec des signatures incorrectes (META-INF/*.SF).


Syntaxes alternatives pour java

Il existe trois syntaxes alternatives pour le lancement de programmes Java à l'aide de java command.

1) La syntaxe utilisée pour lancer un fichier JAR "exécutable" est la suivante:

  java [ <options> ] -jar <jar-file-name> [<arg> ...]

par exemple

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

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

2) La syntaxe de lancement d'une application à partir d'un module (Java 9 et versions ultérieures) est la suivante:

  java [ <options> ] --module <module>[/<mainclass>] [<arg> ...]

Le nom de la classe de point d'entrée est soit défini par <module>lui - même, soit donné par l'option <mainclass>.

3) À partir de Java 11, vous pouvez compiler et exécuter un seul fichier de code source et l'exécuter avec la syntaxe suivante:

  java [ <options> ] <sourcefile> [<arg> ...]

où est (généralement) un fichier avec le suffixe ".java".

Pour plus de détails, veuillez vous référer à la documentation officielle de la javacommande de la version Java que vous utilisez.


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. Celles-ci sont généralement à l' abri de cette exception particulière, car l'EDI utilise ses propres mécanismes pour construire le chemin de classe d'exécution, identifier la classe principale et créer la javaligne de commande.

Cependant, il est toujours possible que cette exception se produise, si vous faites des choses derrière le dos de l'EDI. 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 "principale" vers un autre endroit du système de fichiers sans en informer Eclipse , Eclipse lancerait involontairement la JVM avec un chemin de classe incorrect.

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

Il est également possible pour un IDE de se confondre simplement. Les IDE sont des logiciels extrêmement compliqués comprenant de nombreuses parties en interaction. Beaucoup de ces parties adoptent différentes stratégies de mise en cache afin de rendre l'IDE dans son ensemble réactif. Ceux-ci peuvent parfois mal tourner, et un des symptômes possibles est le problème lors du lancement des applications. Si vous pensez que cela pourrait se produire, cela vaut la peine d'essayer d'autres choses comme le redémarrage de votre IDE, la reconstruction du projet, etc.


Autres références

Stephen C
la source
43
J'ai eu ce problème lorsque j'essayais d'exécuter une classe avec une bibliothèque tierce. J'ai invoqué java comme ceci java -cp ../third-party-library.jar com.my.package.MyClass:; cela ne fonctionne pas, à la place, il est également nécessaire d'ajouter le dossier local au chemin de classe (séparé par :, comme ceci java -cp ../third-party-library.jar:. com.my.package.MyClass
:,
23
Après des années de programmation java, j'ai quand même réussi à finir sur cette page. Pour moi, le problème était que la syntaxe du chemin de classe dépend du système d'exploitation . Je suis un peu nouveau dans la programmation sur Windows et je n'en avais aucune idée.
keyser
5
Notes supplémentaires, point 2 sauve-moi! Il est triste de voir que javacela ne dit pas qu'il ne trouve pas de classe importée, mais plutôt la classe principale que vous essayez d'exécuter. C'est trompeur, même si je suis sûr qu'il y a une raison à cela. J'ai eu le cas où javaje savais exactement où était ma classe, mais il n'a pas pu trouver l'une des classes importées. Au lieu de dire cela, il s'est plaint de ne pas trouver ma classe principale. Vraiment, ennuyeux.
MSX
J'ai eu ce problème deux fois dans Eclipse. La première fois, la signature de main () était incorrecte. La deuxième fois que j'ai renommé un .jar, et même si j'ai ajouté le nouveau au chemin de génération, Eclipse n'a pas trouvé l'ancien, donc le projet n'a pas compilé, avec cette erreur. J'ai dû supprimer le fichier .jar de Projet> Propriétés> Chemin de génération Java> Bibliothèques.
GregT
Je l'ai rencontré une troisième fois. J'ai exécuté le programme à partir d'un fichier de commandes Windows 10 et mis le nom .jar dans une variable (appelée avec "-cp% jarname%; lib *"). J'ai par erreur mis un espace supplémentaire à la fin du nom du pot, et cela a provoqué l'erreur.
Tour du
239

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

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

java HelloWorld.class

Utilisez plutôt ceci:

java HelloWorld
panoet
la source
3
Le problème est que cette solution ne fonctionne que pour les classes Java déclarées dans le package par défaut sans dépendances de fichier JAR. (Et même alors, pas tout le temps.) La plupart des programmes Java ne sont pas si simples.
Stephen C
1
comme Stephen l'a dit, cela ne fonctionne qu'avec le "package par défaut" - ce qui signifie aucune déclaration de package en haut du fichier. Pour un test rapide d'un code, j'ai fait: javac TestCode.javasuivi dejava TestCode
Someone Somewhere
Cela n'a pas fonctionné pour moi. Il dit toujours: "Impossible de trouver ou de charger la classe principale HelloWorld"
Jim
java -jar HelloWorld.jar est également une option
BMaximus
12
Je devais fairejava -classpath . HelloWorld
Chris Prince
136

Si vos classes sont dans des packages, vous devez cdaccéder au répertoire racine de votre projet et exécuter en utilisant le nom complet de la classe (packageName.MainClassName).

Exemple:

Mes cours sont ici:

D:\project\com\cse\

Le nom complet de ma classe principale est:

com.cse.Main

Je cdreviens donc au répertoire racine du projet:

D:\project

javaExécutez ensuite la commande:

java com.cse.Main

Cette réponse est pour sauver les programmeurs Java débutants de la frustration causée par une erreur courante, je vous recommande de lire la réponse acceptée pour une connaissance plus approfondie du chemin de classe Java.

tharinduwijewardane
la source
2
Cette réponse fait toute une série d'hypothèses. Et il existe d'autres moyens d'y parvenir. Au lieu de suivre aveuglément les conseils ci-dessus, je recommanderais aux gens de prendre le temps de lire les liens dans ma réponse qui expliquent comment fonctionne le chemin de classe Java. Il vaut mieux COMPRENDRE ce que vous faites ...
Stephen C
2
Cette réponse fait les hypothèses exactes dont j'avais besoin :) J'étais situé dans le répertoire du fichier .class et java.exe ne fonctionnait pas. Une fois que j'ai cd-ed ci-dessus et couru avec le nom du package inclus dans la ligne de commande, cela a fonctionné.
Nick Constantine
61

Si vous définissez la classe principale et la méthode principale dans apackage , vous devez les exécuter sur le répertoire hiérarchique, en utilisant le nom complet de la classe ( packageName.MainClassName).

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.Classdans le package comme répertoire ./com/test/Main.Java. Et dans le répertoire racine, utilisez java com.test.Main.

M-Razavi
la source
1
Voir «Notes supplémentaires # 1» de ma réponse. Pour une meilleure explication de ce problème.
Stephen C
14
@StephenC Oui, votre réponse est plus complète (et bien sûr, +1), mais cette réponse particulière contenait le mot "package", ce qui m'a permis de trouver rapidement ce dont j'avais besoin. Et ça a marché. Donc +1 Razavi. StephenC, le vôtre n'a pas l'exemple de package simple dont j'avais besoin car je suis nouveau sur Java.
kmort
5
C'était exactement mon problème. J'ai parcouru des tonnes de documents Java et cet exemple concret était ce dont j'avais besoin
John
1
Oui, l'exemple concret est sympa, cela a parfaitement fonctionné. Je suis sûr que la réponse principale est très complète, mais il était difficile de voir l'arbre de la forêt. Nice one @Razavi
Pixel
1
J'aime cette réponse courte et utile au lieu d'une acceptée!
Spara
46

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

javac HelloWorld.java
java -cp . HelloWorld
Enamul Hassan
la source
2
Ce n'est pas une bonne recommandation. Vous dépendez de la variable d'environnement CLASSPATH qui n'est pas définie ou dont la valeur est cohérente avec ".". Oui, cela fonctionne dans de nombreux cas, mais pas dans d'autres.
Stephen C
Eh bien, cela javac -classpath . HelloWorld.javaaurait certainement fonctionné! Et c'est une meilleure solution dans votre cas.
Stephen C
2
Si vous avez 'package com.some.address' comme première ligne - cela ne fonctionnera pas. Vous devrez commenter 'adresse du package'.
Joe
1
@Joe - Ce hack (commentant le paquet) fonctionnera (dans certains cas) mais c'est une mauvaise idée. Une meilleure idée est d'apprendre / comprendre la cause du problème et de mettre en œuvre la bonne solution.
Stephen C
36

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

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

  2. Créez le 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 l' -classpathoption permettant à JRE de savoir où trouver la classe:

    java -classpath C:\temp Temp Hello!
Celebes
la source
3
Dans Ubuntu, je devais également spécifier le chemin. Je ne comprends pas pourquoi il ne peut pas utiliser le répertoire de travail actuel par défaut. Je suis convaincu que Java est sponsorisé par les fabricants de claviers !!
disparu le
1
@gone - La raison pour laquelle "." n'est pas dans $ PATH par défaut, c'est qu'il s'agit d'un piège de sécurité. seas.upenn.edu/cets/answers/dot-path.html
Stephen C
Merci beaucoup pour cela ... même si vous ne savez pas pourquoi java n'a pas pu trouver le chemin de classe même après l'avoir défini dans les variables d'environnement.
akash89
@ akash89 - Les raisons les plus probables étaient: 1) javane regardait pas $ CLASSPATH (parce que vous avez utilisé -classpath ou -jar) ou 2) le paramètre classpath n'était pas défini dans l'environnement qui n'était pas en vigueur dans le contexte qui javaétait courir; par exemple parce que vous n'avez pas "source" le fichier où ont été ajoutées les commandes setenv dans le shell droit.
Stephen C
J'ai encore une erreur: Impossible de trouver ou de charger la classe principale Temp, quelqu'un pourrait-il aider!
Star
27

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 est introuvable
  2. La classe principale n'a pas pu être chargée (ce cas n'est pas entièrement traité dans la réponse acceptée)

La classe principale est introuvable en cas de faute de frappe ou de syntaxe incorrecte dans le nom de classe complet ou si elle n'existe pas dans le chemin de classe fourni .

La classe principale n'a pas pu être chargée lorsque la classe ne peut pas être lancée , généralement la classe principale étend une autre classe et cette classe n'existe pas dans le chemin de classe fourni.

Par exemple:

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

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

Xiao Peng - ZenUML.com
la source
"Fondamentalement", il y a aussi beaucoup d'autres catégories. Et le problème de superclasse manquant est un sous-cas très inhabituel. (Tellement inhabituel que je ne l'ai jamais vu ... dans les questions posées sur ce site.)
Stephen C
Il y en a DEUX car l'erreur indique "Impossible de trouver ou de charger la classe principale". S'il existe d'autres catégories, veuillez m'en aviser. Je l'ai vu, alors je veux juste le partager ici, peut-être que quelqu'un d'autre en aura besoin.
Xiao Peng - ZenUML.com
1
Je l'aurais révisé en quelque chose comme "Vous devez inclure toutes les classes nécessaires pour lancer la classe principale afin d'éviter cette erreur particulière". Je n'essaye pas de te convaincre. C'est juste une façon que j'aimerais voir. J'ai laissé la réponse ici juste pour les gens qui aimeraient lire les choses de cette façon. N'allons pas plus loin dans cette discussion :) J'ai changé ma déclaration en "pas entièrement discuté dans la réponse acceptée" et j'espère que vous vous sentirez mieux.
Xiao Peng - ZenUML.com
5
Cette information est cruciale et mérite une mention explicite (c'est la seule réponse qui mentionne extends). Je viens d'apprendre à la dure que lorsque la classe principale ne se charge pas car elle en étend une autre qui ne peut pas être trouvée , java ne signale pas quelle classe réelle n'a pas été trouvée (contrairement NoClassDefFoundError). Alors oui, cela arrive, et c'est une situation époustouflante quand vous ne le savez pas.
Hugues M.
1
Dans cette situation, existe-t-il un moyen de savoir exactement quelle classe de dépendance ne parvient pas à se charger?
Carlos A. Ibarra
16

J'ai eu une telle erreur dans ce cas:

java -cp lib.jar com.mypackage.Main

Il fonctionne avec ;pour Windows et :pour Unix:

java -cp lib.jar; com.mypackage.Main
Yamahar1sp
la source
Oui. C'est très probablement parce que votre Mainfichier n'est pas dans le fichier JAR. -cp lib.jar;signifie la même chose que -cp lib.jar;. le répertoire courant est inclus dans le chemin de classe.
Stephen C
Enfin résolu le problème pour unix .. merci (fonctionne avec :)
Vicky
16

Essayez -Xdiag .

La réponse de Steve C couvre bien les cas possibles, mais parfois, déterminer si la classe n'a pas pu être trouvée ou chargée peut ne pas être aussi simple. Utiliser java -Xdiag(depuis JDK 7). Cela imprime une belle trace de pile qui donne un indice sur la signification du message Could not find or load main class.

Par exemple, il peut vous diriger vers d'autres classes utilisées par la classe principale qui sont introuvables et empêcher le chargement de la classe principale.

jan.supol
la source
16

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 se trouve dans le package 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 la javacommande attend classpath et pour cette raison nous ajoutons -cp .de prendre le dossier actuel comme référence pour classpath.

shaILU
la source
Cela ne fonctionne que dans des cas simples. Les cas plus compliqués nécessitent un chemin de classe plus compliqué.
Stephen C
Et pour >> vraiment << les cas simples, ce -cp .n'est pas nécessaire, car si il $CLASSPATHn'est pas défini, alors .c'est le chemin de classe par défaut.
Stephen C
Non Stephen, plusieurs fois dans le chemin de classe par défaut de Windows ne fonctionne pas. Je l'ai essayé sur trois machines différentes, vous pouvez également l'essayer.
shaILU
C'est probablement parce que vous avez défini la variable d'environnement% CLASSPATH% quelque part. Si vous le faites, vous n'utilisez pas le chemin de classe par défaut. (Qu'est-ce que la echo %CLASSPATH%sortie?) Et non, je ne peux pas vérifier car je n'ai pas de PC Windows.
Stephen C
2
Cela a fonctionné pour moi lorsque j'ai essayé d'exécuter un programme simple à partir de la ligne de commande
SnuKies
15

Parfois, ce qui pourrait causer le problème n'a rien à voir avec la classe principale, et j'ai dû le découvrir à la dure. C'est 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, de l'ajouter à nouveau et cela a bien fonctionné à nouveau.

Eduardo Dennis
la source
1
Il semble que le problème était que vous aviez un chemin de classe incorrect en raison d'une "référence" cassée dans votre projet dans votre IDE. Je mettrai à jour ma réponse pour couvrir ce cas.
Stephen C
@StephenC et EduardoDennis, C'était qu'ici aussi, il manquait un pot, ce pot contenait une interface dont la classe principale dépendait pour être instanciée. Ainsi, le message d'erreur est trop large. Je devrais dire "n'a pas pu trouver" si le fichier de classe n'est pas trouvé et "n'a pas pu se charger (dépendances manquantes)" s'il manque quelque chose d'autre mais pas le fichier lui-même, donc le message d'erreur étant trop large est trompeur si vous vous concentrez uniquement sur la partie "trouver" :(
Aquarius Power
@AquariusPower - Il aurait dû y avoir une trace supplémentaire "causée par" pour l'exception "cause" qui disait que la classe était manquante. Si vous voulez suggérer aux développeurs Java qu'ils changent un message d'erreur qui dit que depuis plus de 20 ans ... n'hésitez pas. (Je pense que le message d'erreur est correct. Le problème était que >> vous << avez restreint la mauvaise clause.)
Stephen C
@StephenC ce que je voulais dire, c'est qu'ils ont sûrement accès aux informations si le fichier de la classe principale est disponible ou non, alors pourquoi ne pas nous montrer un meilleur message d'erreur disant qu'un tel fichier est manquant. D'autre part, ils pourraient également dire "Le fichier a été trouvé mais n'a pas pu être chargé" à ce moment-là, nous nous concentrerions rapidement sur les dépendances au lieu de perdre une demi-journée à rechercher et tester des choses à comprendre. Juste ce que je voulais dire :). Ils peuvent le faire de manière limitée pendant plus de 20 ans, mais ils peuvent l'améliorer et nous sommes là pour vous le garantir grâce à nos critiques et plaintes! : D
Aquarius Power
Veuillez comprendre ce que >> je << voulais dire. Se plaindre à ce sujet dans un commentaire obscur sur les questions et réponses de 3 ans ne va rien faire. Les personnes susceptibles de donner suite à vos réclamations ne le remarqueront pas. Si vous voulez faire quelque chose de constructif, soumettez un patch. (Je n'évalue pas vos chances, mais elles seront plus grandes que si vous vous contentez de vous plaindre.)
Stephen C
10

Dans ce cas, vous avez:

Impossible de trouver ou de charger la classe principale ? Classpath

C'est parce que vous utilisez "-classpath", mais le tiret n'est pas le même tiret utilisé par javasur l'invite de commande. J'ai eu ce problème en copiant et en collant du Bloc-notes vers cmd.

Nathan Williams
la source
2
Hou la la! C'est une cause totalement bizarre! (Mais il vous sert bien pour utiliser le Bloc-notes au lieu d'un véritable éditeur de texte :-))
Stephen C
10

J'ai eu le même problème et j'ai finalement trouvé mon erreur :) J'ai utilisé cette commande pour la compilation et cela a fonctionné correctement:

javac -cp "/home/omidmohebbi/AAAATest/jars/core-1.7.jar:/home/omidmohebbi/AAAATest/jars/javase-1.7.jar:/home/omidmohebbi/AAAATest/jars/qrgen-1.2.jar" qrcode.java

Mais cette commande n'a pas fonctionné pour moi (je n'ai pas pu trouver ou charger la classe principale qrcode):

java -cp "/home/omidmohebbi/AAAATest/jars/core-1.7.jar:/home/omidmohebbi/AAAATest/jars/javase-1.7.jar:/home/omidmohebbi/AAAATest/jars/qrgen-1.2.jar" qrcode

Enfin, je viens d'ajouter le caractère «:» à la fin du chemin de classe et le problème a été résolu:

java -cp "/home/omidmohebbi/AAAATest/jars/core-1.7.jar:/home/omidmohebbi/AAAATest/jars/javase-1.7.jar:/home/omidmohebbi/AAAATest/jars/qrgen-1.2.jar:" qrcode
Omid Mohebbi
la source
7

Dans mon cas, une erreur s'est produite car j'avais fourni le nom du fichier source au lieu du nom de la classe.

Nous devons fournir le nom de classe contenant la méthode principale à l'interpréteur.

KawaiKx
la source
Oui. Voir mon exemple # 2 des mauvaises façons de spécifier le nom de classe !!
Stephen C
7

Cela pourrait vous aider si votre cas est spécifiquement comme le mien: en tant que débutant, j'ai également rencontré ce problème lorsque j'ai essayé d'exécuter un programme Java.

Je l'ai compilé comme ceci:

javac HelloWorld.java

Et j'ai essayé de courir aussi avec la même extension:

java Helloworld.java

Lorsque j'ai supprimé .javaet réécrit la commande comme java HelloWorld, le programme s'est parfaitement déroulé. :)

Ramesh Pareek
la source
2
C'est parce que vous exécutez la version compilée de votre .java. Il exécute actuellement le fichier .class
Jason V
Pour mémoire, c'est la même chose que la raison n ° 1, l'exemple n ° 5 dans ma réponse ...
Stephen C
6

Il semble que toutes les réponses soient destinées aux utilisateurs de Windows. Pour Mac, le séparateur de chemin de classe ne l'est :pas ;. Comme une erreur lors de la définition du chemin de classe à l'aide ;n'est pas levée, cela peut être difficile à découvrir si vous venez de Windows vers Mac.

Voici la commande Mac correspondante:

java -classpath ".:./lib/*" com.test.MyClass

Où dans cet exemple le paquet est com.testet un libdossier doit également être inclus sur classpath.

ciel bleu
la source
2
Sous Linux comme sur Mac.
Alex78191
Pourquoi /*est-il nécessaire?
Alex78191
Il s'agit d'une syntaxe générique. (Ce n'est pas obligatoire. Vous pouvez explicitement lister les JAR si vous le souhaitez.)
Stephen C
6

entrez la description de l'image ici

Emplacement du fichier de classe: C: \ test \ com \ company

Nom du fichier: Main.class

Nom de classe complet: com.company.Main

Commande en ligne de commande:

java  -classpath "C:\test" com.company.Main

Notez ici que le chemin de classe n'inclut PAS \ com \ company

developer747
la source
6

J'ai passé beaucoup de temps à essayer de résoudre ce problème. Je pensais que je définissais mal mon chemin de classe, mais le problème était que j'ai tapé:

java -cp C:/java/MyClasses C:/java/MyClasses/utilities/myapp/Cool  

au lieu de:

java -cp C:/java/MyClasses utilities/myapp/Cool   

Je pensais que la signification de pleinement qualifié signifiait inclure le nom de chemin complet au lieu du nom de package complet.

mathewbruens
la source
J'ai mis à jour ma réponse pour essayer de résoudre cette confusion.
Stephen C
2
Aucun de ces éléments n'est correct. La classe doit être donnée en tant que utilities.myapp.Coolou quel que soit son nom de package, le cas échéant.
Marquis de Lorne
5

Définissez d'abord le chemin à l'aide de cette commande;

set path="paste the set path address"

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

arun
la source
4
Cela n'aide pas. Cette question concerne les programmes Java, pas les exécutables ordinaires. Java n'utilise pas PATH pour localiser quoi que ce soit, et si "cd" l'aide alors par chance plutôt que par jugement.
Stephen C
if "cd" helps then it by luck rather than by judgement. C'est faux (je crois), car java utilise le répertoire courant .dans le chemin de classe par défaut.
GKFX
2
@GKFX - C'est ce que je veux dire. À moins que vous ne sachiez que vous utilisez le chemin de classe par défaut (ou un chemin de classe avec "." Dessus), "cd" n'aura aucun effet. Cette solution fonctionne plus par chance (ie deviner / espérer que "." Est sur le chemin de classe) que par jugement (ie vérifier que "." Est sur le chemin de classe). De plus, vous vous trompez sur la valeur par défaut. Java utilise "." comme chemin de classe par défaut, pas comme partie du chemin de classe par défaut.
Stephen C
5

Ce qui a résolu le problème dans mon cas était:

Faites un clic droit sur le projet / classe que vous souhaitez exécuter, puis Run As-> Run Configurations. Ensuite, vous devez soit corriger votre configuration existante, soit en ajouter de la manière suivante:

ouvrez l' Classpathonglet, cliquez sur le Advanced...bouton puis ajoutez le bindossier de votre projet.

syntagme
la source
5

Si vous utilisez Maven pour créer le fichier JAR, assurez-vous de spécifier la classe principale dans le fichier pom.xml:

<build>
    <plugins>
        <plugin>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>class name us.com.test.abc.MyMainClass</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</build>
Junchen Liu
la source
4

C'est un cas spécifique, mais depuis que je suis venu sur cette page à la recherche d'une solution et que je ne l'ai pas trouvée, je vais l'ajouter ici.

Windows (testé avec 7) n'accepte pas les caractères spéciaux (comme á) dans les noms de classe et de package. Linux le fait cependant.

J'ai découvert cela lorsque j'ai construit un .jarNetBeans et essayé de l'exécuter en ligne de commande. Il a fonctionné dans NetBeans mais pas en ligne de commande.

GuiRitter
la source
4

Sur Windows, mettez .;la valeur CLASSPATH au début.

Le . (point) signifie "regarder dans le répertoire courant". Il s'agit d'une solution permanente.

Vous pouvez également le régler "une fois" avec set CLASSPATH=%CLASSPATH%;.. Cela durera aussi longtemps que votre fenêtre cmd sera ouverte.

Nenad Bulatovic
la source
1
Ces conseils peuvent ou non vous aider. Cela aidera si l'arborescence des classes contenant les classes dans le répertoire courant. Ce ne sera pas le cas s'ils ne le sont pas. En fait, je ne ferais pas ça. Au lieu de cela, je créerais un script d'encapsuleur à une ligne qui fonctionnerait, que l'utilisateur soit ou non dans le "bon" répertoire.
Stephen C
4

Vous devez vraiment le faire à partir du srcdossier. Là, vous tapez la ligne de commande suivante:

[name of the package].[Class Name] [arguments]

Disons que votre classe est appelée CommandLine.classet que le code ressemble à ceci:

package com.tutorialspoint.java;

    /**
     * Created by mda21185 on 15-6-2016.
     */

    public class CommandLine {
        public static void main(String args[]){
            for(int i=0; i<args.length; i++){
                System.out.println("args[" + i + "]: " + args[i]);
            }
        }
    }

Ensuite, vous devriez cddans le dossier src et la commande que vous devez exécuter devrait ressembler à ceci:

java com.tutorialspoint.java.CommandLine this is a command line 200 -100

Et la sortie sur la ligne de commande serait:

args[0]: this
args[1]: is
args[2]: a
args[3]: command
args[4]: line
args[5]: 200
args[6]: -100
Mike. ré
la source
2
Une classe ne peut pas être appelée "CommandLine.class". Ce serait une erreur de syntaxe Java. (Ce que vous voulez dire, c'est que le fichier contenant la classe compilée s'appelle "CommandLine.class" ...). L'autre problème est que votre instruction de "cd vers le répertoire source" ne fonctionne que si vous avez compilé le code >> dans << l'arborescence du répertoire source. Enfin, si votre compilation utilise un argument "-cp", vous avez besoin d'un équivalent lorsque vous exécutez.
Stephen C
Dans mon projet, j'ai le dossier src et le dossier bin à la racine. J'ai dû cdentrer srcpuis exécuter la commande java ../bin com.blah.blah.MyClassqui fonctionnait pour moi. Merci donc pour l'astuce!
tamj0rd2
3

En Java, lorsque vous exécutez parfois la machine virtuelle Java à partir de la ligne de commande à l'aide de l'exécutable java et que vous essayez de démarrer un programme à partir d'un fichier de classe avec public static void main (PSVM), vous pouvez rencontrer l'erreur ci-dessous même si le paramètre classpath la JVM est précise et le fichier de classe est présent sur le chemin de classe:

Error: main class not found or loaded

Cela se produit si le fichier de classe avec PSVM n'a pas pu être chargé. Une raison possible à cela est que la classe peut implémenter une interface ou étendre une autre classe qui n'est pas sur le chemin de classe. Normalement, si une classe n'est pas sur le chemin de classe, l'erreur renvoyée l'indique comme telle. Mais, si la classe utilisée est étendue ou implémentée, java ne peut pas charger la classe elle-même.

Référence: https://www.computingnotes.net/java/error-main-class-not-found-or-loaded/

Anandaraja Ravi
la source
1
Avez-vous lu la réponse acceptée? Votre réponse ajoute-t-elle quelque chose de nouveau?
Stephen C
1
@StephenC J'ai essayé de trouver une raison dans votre liste en regardant les catégories "Raison" et leurs points. Je n'ai pas pu trouver le point correspondant dans le titre "Reason # 1" et "Reason # 2" ne ressemblait pas à mon cas (parce que j'étais sûr qu'il n'y avait aucun problème avec classpath lui-même). J'ai trouvé la raison en effectuant des expériences et j'ai été surpris que, dans mon cas, l'erreur "classe principale non trouvée" ait été affichée car l'implémentation de l'interface n'était pas sur le chemin de la classe. Bien sûr, vous pouvez dire "vous devez lire tout ce qui est décrit dans le post", mais il me semble que votre liste de raisons peut être améliorée.
gumkins
3

Lors de l' exécution de la javaavec l' -cpoption de comme annoncé dans Windows PowerShell , vous pouvez obtenir une erreur qui ressemble à quelque chose comme:

The term `ClassName` is not recognized as the name of a cmdlet, function, script ...

Pour que PowerShell accepte la commande, les arguments de l' -cpoption doivent être contenus entre guillemets comme dans:

java -cp 'someDependency.jar;.' ClassName

Formater la commande de cette façon devrait permettre à Java de traiter correctement les arguments de chemin de classe.

Chezzwizz
la source
3

J'ai également rencontré des erreurs similaires lors du test d'une connexion Java MongoDB JDBC. Je pense qu'il est bon de résumer ma solution finale en bref afin qu'à l'avenir, n'importe qui puisse examiner directement les deux commandes et soit prêt à poursuivre.

Supposons que vous vous trouviez dans le répertoire où se trouvent votre fichier Java et les dépendances externes (fichiers JAR).

Compiler:

javac -cp mongo-java-driver-3.4.1.jar JavaMongoDBConnection.java
  • -cp - argument classpath; passer tous les fichiers JAR dépendants un par un
  • * .java - Il s'agit du fichier de classe Java qui a la méthode principale. sdsd

Courir:

java -cp mongo-java-driver-3.4.1.jar: JavaMongoDBConnection
  • Veuillez observer les deux points (Unix) / virgule (Windows) après la fin de tous les fichiers JAR de dépendance
  • À la fin, observez le nom de la classe principale sans aucune extension (pas de .class ou .java)
khichar.anil
la source
Tout cela suppose que 1) JavaMongoDBConnectionn'a pas de package et 2) que vous ne changez pas de répertoire. Elle est pour le moins fragile. Et en n'expliquant pas les problèmes, cela amènera les débutants à essayer cette approche dans des situations où cela ne fonctionnera pas . En bref, cela encourage les "techniques de programmation vaudou": en.wikipedia.org/wiki/Voodoo_programming
Stephen C
3

D'accord, il existe déjà de nombreuses réponses, mais personne n'a mentionné le cas où les autorisations de fichiers peuvent être le coupable.

Lors de l'exécution, un utilisateur peut ne pas avoir accès au fichier JAR ou à l'un des répertoires du chemin. Par exemple, considérez:

Fichier Jar dans /dir1/dir2/dir3/myjar.jar

L'utilisateur 1 propriétaire du fichier JAR peut effectuer:

# Running as User1
cd /dir1/dir2/dir3/
chmod +r myjar.jar

Mais ça ne marche toujours pas:

# Running as User2
java -cp "/dir1/dir2/dir3:/dir1/dir2/javalibs" MyProgram
Error: Could not find or load main class MyProgram

Cela est dû au fait que l'utilisateur en cours d'exécution (User2) n'a pas accès à dir1, dir2, ou javalibs ou dir3. Cela peut rendre quelqu'un fou lorsque User1 peut voir les fichiers et y accéder, mais l'erreur se produit toujours pour User2.

biocyberman
la source
2

J'ai eu cette erreur après avoir fait mvn eclipse:eclipse Cela a .classpathun peu gâché mon fichier.

J'ai dû changer les lignes .classpathde

<classpathentry kind="src" path="src/main/java" including="**/*.java"/>
<classpathentry kind="src" path="src/main/resources" excluding="**/*.java"/>

à

<classpathentry kind="src" path="src/main/java" output="target/classes" />
<classpathentry kind="src" path="src/main/resources" excluding="**"  output="target/classes" />
Jaanus
la source
2

Je n'ai pas pu résoudre ce problème avec les solutions énoncées ici (bien que la réponse indiquée ait, sans aucun doute, clarifié mes concepts). J'ai rencontré ce problème deux fois et à chaque fois, j'ai essayé différentes solutions (dans l'IDE Eclipse).

  • Tout d'abord, j'ai rencontré plusieurs mainméthodes dans différentes classes de mon projet. Ainsi, j'avais supprimé la mainméthode des classes suivantes.
  • Deuxièmement, j'ai essayé la solution suivante:
    1. Faites un clic droit sur le répertoire principal de mon projet.
    2. Dirigez-vous vers la source, puis nettoyez et respectez les paramètres par défaut et cliquez sur Terminer. Après quelques tâches d'arrière-plan, vous serez dirigé vers votre répertoire de projet principal.
    3. Après cela, je ferme mon projet, le rouvre et boum, j'ai finalement résolu mon problème.
Anus Kaleem
la source
1
La suppression de mainméthodes ne résoudra pas le problème. Il n'y a rien de mal techniquement avec une application qui a plusieurs points d'entrée.
Stephen C