Problème jar

Résolu/Fermé
cb92140 Messages postés 18 Date d'inscription lundi 16 février 2009 Statut Membre Dernière intervention 26 novembre 2014 - 2 juin 2013 à 12:41
cb92140 Messages postés 18 Date d'inscription lundi 16 février 2009 Statut Membre Dernière intervention 26 novembre 2014 - 2 juin 2013 à 17:21
Bonjour,

J'ai une appli qui marche en la compilant avec javac : elle produit plusieurs .class, dont Main.class, et quand je lance ">java Main test.txt" tout va bien.

J'ai alors l'ambition de tout regrouper dans un .jar : je crée un "manifest.text" pour dire où se trouve la Main-Class, je fais un "jar cvfm cup.jar manifest.txt *.class", et j'essaie d'exécuter "java -jar cup.jar test.txt", et je me retrouve avec un "Exception in thread "main" java.lang.NoClassDefFoundError: java_cup/runtime/Scanner". Avec le même CLASSPATH.

QUESTION : pourquoi java ne trouve-t-il plus ses petits quand on travaille avec le jar qui regroupe les classes nécessaires ?

Pour info, mon appli est simplement l'exemple "cup" de la distribution JFLEX, j'ai rien touché au code, et je travaille sous UBUNTU.

Merci pour toute aide...

6 réponses

KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
2 juin 2013 à 13:28
NoClassDefFoundError: java_cup/runtime/Scanner

Les noms de classes sont séparés par des points, pas par des slashs, tu devrais normalement avoir java_cup.runtime.Scanner à condition bien sûr que cette classe Scanner possède une méthode main.
0
cb92140 Messages postés 18 Date d'inscription lundi 16 février 2009 Statut Membre Dernière intervention 26 novembre 2014 1
2 juin 2013 à 14:02
Merci de cette réponse.

Je crois que les slash ne soient qu'un choix d'affichage. Le message complet est:
Exception in thread "main" java.lang.NoClassDefFoundError: java_cup/runtime/Scanner
Caused by: java.lang.ClassNotFoundException: java_cup.runtime.Scanner
....
....

CUP est un équivalent de bison/yacc sous java, et JFLEX un équivalent de flex/lex, il est distribué sous forme d'un .jar, et il définit une classe Scanner dans son runtime. Dans l'exemple donné dans la distribution, il est bien défini un :
class Lexer implements java_cup.runtime.Scanner {...}
et le lien se fait bien quand on exécute directement à partir de la classe Main.

!! Mais pas quand les classes de l'appli sont regroupées dans un jar...
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
2 juin 2013 à 14:18
Si ta méthode main est dans la classe Main, c'est cette classe Main qui doit apparaître dans le Manifest, pas la classe Scanner...

Manifest-Version: 1.0
Main-Class: Main

Et le choix des slashs ou des points est important, les slashs séparent les noms de fichiers dans l'arborescence de l'archive, alors que les points séparent les noms de classe dans l'arborescence des classes. Ici c'est une classe qu'il faut mettre, pas le chemin d'accès aux fichiers.
0
cb92140 Messages postés 18 Date d'inscription lundi 16 février 2009 Statut Membre Dernière intervention 26 novembre 2014 1
2 juin 2013 à 16:45
Je suis bien d'accord avec tout cela... Les sources sont bonnes puisque l'appli s'exécute bien en lancement par ">java Main test.txt". La classe Main et les autres sont bien dans le "cup.jar" et ">java -jar cup.jar test.txt" échoue cependant.

Le fichier MANIFEST.MF est correct :

Manifest-Version: 1.0
Created-By: 1.6.0_27 (Sun Microsystems Inc.)
Main-Class: Main

Je pense que tout cela ne tient qu'à un "détail", mais lequel...
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
2 juin 2013 à 16:47
Un détail : ton fichier manifest doit finir par une ligne vide. Tu auras donc 4 lignes :

1# Manifest-Version: 1.0 
2# Created-By: 1.6.0_27 (Sun Microsystems Inc.) 
3# Main-Class: Main 
4# 
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cb92140 Messages postés 18 Date d'inscription lundi 16 février 2009 Statut Membre Dernière intervention 26 novembre 2014 1
2 juin 2013 à 17:09
Il y a bien une ligne vide :)
La trace d'exécution du make est :

javac Main.java Lexer.java parser.java
jar cvfm cup.jar manifest.txt *.class
added manifest
adding: CUP$parser$actions.class(in = 3541) (out= 1490)(deflated 57%)
adding: Lexer.class(in = 7260) (out= 4071)(deflated 43%)
adding: Main.class(in = 678) (out= 443)(deflated 34%)
adding: parser.class(in = 3125) (out= 1487)(deflated 52%)
adding: sym.class(in = 516) (out= 317)(deflated 38%)
java Main test.txt > output.txt
cat output.txt
2 + 4 = 6
5 * ( 6 - 3 ) + 1 = 16
6 / 3 * 5 + 20 = 30
4 * 76 / 31 = 9
1 - 1 - 1 = -1
java -jar cup.jar test.txt
Exception in thread "main" java.lang.NoClassDefFoundError: java_cup/runtime/Scanner
Caused by: java.lang.ClassNotFoundException: java_cup.runtime.Scanner
at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
Could not find the main class: Main. Program will exit.
make: *** [output.txt] Error 1
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
2 juin 2013 à 17:19
Il faudrait regarder ce qu'il y a dans ton fichier .jar (tu peux l'ouvrir avec WinRar par exemple), mais je pense que *.class n'ajoute que les classes qui sont dans le répertoire courant, pas les classes qui sont dans des packages comme java_cup.
Il faudrait alors faire "jar cvfm cup.jar manifest.txt *.class java_cup/*.class" ou un truc comme ça.
0
cb92140 Messages postés 18 Date d'inscription lundi 16 février 2009 Statut Membre Dernière intervention 26 novembre 2014 1
2 juin 2013 à 17:21
J'AI TROUVé !!!!!!

Il faut aussi déclarer le Class-Path dans le manifest, même si la variable d'environnement CLASSPATH est correctement déclarée.

La commande "java -jar cup.jar test.txt" marche en rajoutant dans manifest la ligne
Class-Path: /usr/share/java/JFlex.jar /usr/share/java/cup.jar

Merci pour ton aide !
0