web-dev-qa-db-fra.com

Java ne trouve pas la classe principale

J'ai écrit le fichier source Java suivant (Hello.Java):

package com;

public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello!");
    }
}

Je sauve ceci à C:/tmpjava/Hello.Java.

À partir de la ligne de commande, je navigue dans ce répertoire et lance javac Hello.Java. Puis je lance dir:

  • Hello.class
  • Hello.Java

Ensuite, à partir du même répertoire que celui où je viens d’exécuter javac, j’exécute Java Hello.class et reçois:

Exception in thread "main" Java.lang.NoClassDefFoundError: Hello/class
Caused by: Java.lang.ClassNotFoundException: Hello.class
    at Java.net.URLClassLoader$1.run(URLClassLoader.Java:202)
    at Java.security.AccessController.doPrivileged(Native Method)
    at Java.net.URLClassLoader.findClass(URLClassLoader.Java:190)
    at Java.lang.ClassLoader.loadClass(ClassLoader.Java:306)
    at Sun.misc.Launcher$AppClassLoader.loadClass(Launcher.Java:301)
    at Java.lang.ClassLoader.loadClass(ClassLoader.Java:247)
Could not find the main class: Hello.class.  Program will exit.

Que se passe t-il ici?!? Comment javac peut-il fonctionner correctement, mais pas Java?

19
IAmYourFaja

Votre classe Hello appartient au paquetage com. Donc, le nom complet de votre classe est com.Hello. Lorsque vous appelez un programme utilisant Java sur la ligne de commande, vous devez fournir le nom de classe complet de la classe qui contient votre méthode main et omettre le .class, comme suit:

Java com.Hello

Le programme Java a besoin de ce nom de classe qualifié complet pour comprendre la classe à laquelle vous faites référence.

Mais vous avez un autre problème. Le programme Java localise les packages, les sous-packages et les classes qui leur appartiennent à l'aide du système de fichiers. Donc, si vous avez une structure de paquetage comme com.Hello, le programme Java s'attend à trouver un fichier de classe nommé Hello.class dans un répertoire nommé com, comme ceci: com/Hello.class. En fait, vous pouvez observer ce comportement dans la Exception que vous voyez; vous avez utilisé incorrectement Hello.class, que Java interprète comme un package nommé Hello et une classe nommée class et qui recherche la structure de répertoires Hello/class:

Java.lang.NoClassDefFoundError: Hello/class

Mais le compilateur javac does a configuré cette structure de répertoires par défaut. Reportez-vous à la documentation de javac , mais le point important est le suivant: lorsque vous compilez, vous pouvez spécifier un répertoire de destination à l'aide de l'indicateur -d:

-d répertoire

Définissez le répertoire de destination pour les fichiers de classe. Le répertoire de destination doit déjà exister; javac ne créera pas le répertoire de destination. Si une classe fait partie d'un package, javac place le fichier de la classe dans un sous-répertoire reflétant le nom du package, en créant des répertoires en fonction des besoins. Par exemple, si vous spécifiez -d c:\myclasses et que la classe s'appelle com.mypackage.MyClass, le fichier de classe s'appelle c:\myclasses\com\mypackage\MyClass.class.

Si -d n'est pas spécifié, javac place le fichier de classe dans le même répertoire que le fichier source.

La dernière partie en gras est source de confusion pour les débutants et fait partie de votre propre problème.

Donc, vous avez deux alternatives:

  1. Dans votre cas, cela ne pose pas de problème si vous indiquez le répertoire en cours comme répertoire de destination, comme suit (la période . signifie répertoire en cours):

    javac -d . Hello.Java
    

    Si vous appelez le compilateur comme ceci, il créera le répertoire com et y placera votre fichier de classe compilé, comme le programme Java l’attend. Ensuite, lorsque vous exécutez Java comme ci-dessus, à partir de c:\tmpJava, votre programme doit être exécuté.

  2. Vous pouvez configurer votre code source à l'aide d'une structure de répertoires reflétant la structure de votre package: placez votre fichier source Hello.Java dans un répertoire appelé com, dans votre cas: c:\tmpJava\com\Hello.Java. Maintenant, à partir de c:\tmpJava, vous pouvez exécuter votre compilation javac comme ceci:

    javac com\Hello.Java
    

    Vous n'avez pas fourni l'indicateur -d, mais c'est correct, car vous avez créé vous-même la structure de répertoires et citez à nouveau à partir de la documentation ci-dessus:

    Si -d n'est pas spécifié, javac place le fichier de classe dans le même répertoire que le fichier source.

    Encore une fois, lorsque vous exécutez Java comme ci-dessus, votre programme doit être exécuté.

    Notez que cette deuxième alternative est celle couramment utilisée par les programmeurs Java: les fichiers de code source sont organisés dans une structure de répertoires qui reflète la structure du package. 

Dans cette explication, nous avons ignoré le concept du classpath. Vous aurez également besoin de comprendre cela pour écrire des programmes Java, mais dans votre cas de simplement compiler un programme dans le répertoire courant (si vous suivez l'une des deux alternatives ci-dessus lors de la compilation de votre classe), vous pouvez vous échapper sans définir de chemin d'accès aux classes car Par défaut, le programme Java a le répertoire en cours comme chemin de classe. Une autre citation, celle du documentation pour Java :

-cp classpath

Spécifiez une liste de répertoires, d'archives JAR et d'archives Zip pour rechercher des fichiers de classe. Les entrées de chemin de classe sont séparées par des points-virgules (;). La spécification de -classpath ou -cp remplace tout paramètre de la variable d'environnement CLASSPATH.

Si -classpath et -cp ne sont pas utilisés et que CLASSPATH n'est pas défini, le chemin de la classe d'utilisateurs est constitué du répertoire en cours (.).

Notez que lorsque vous utilisez un IDE comme Eclipse pour exécuter votre code Java, cette opération est principalement gérée pour vous, mais vous rencontrez toujours des problèmes de chemin d'accès aux classes. 

40
pb2q

La syntaxe de la commande Java est la suivante:

Java [classname]

ne pas

Java [filename]

Java cherche dans son classpath une classe du nom que vous avez fourni. Habituellement, le chemin d'accès aux classes inclut le répertoire actuel, donc:

Java Hello

... trouvera Hello.class dans le répertoire en cours et exécutera sa méthode main ().

Toutefois, si la classe se trouve ailleurs (comme dans un fichier .jar ou ailleurs dans le système de fichiers), vous pouvez la spécifier avec la variable d'environnement CLASSPATH ou sur la ligne de commande:

Java -cp build/classes Hello
Java -cp build/jars/myjar.jar Hello
9
slim

La classe doit être en C:\tmpjava\com\Hello.class
Et vous devriez courir à partir de C:\tmpjava: Java -cp . com.Hello
Lorsque vous mettez une classe dans un package, il définit la structure de fichier de la classe. C'est à dire. votre classe qui dans le paquet com devrait être dans le dossier com

4
Cratylus

Lancer la commande suivante

Java -cp . com.Hello
2
SiB

Java -classpath c:\tmpjava com.Hello

0
StephenMeyer