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
?
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:
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é.
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.
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
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
Lancer la commande suivante
Java -cp . com.Hello
Java -classpath c:\tmpjava com.Hello