J'essaie de placer une application dans un pot pour un déploiement plus facile. L'application se compile et s'exécute correctement (dans une fenêtre de commande Windows) lorsqu'elle est exécutée sous la forme d'un ensemble de classes accessibles à partir de CLASSPATH. Mais lorsque je lance mes classes et que je tente de l'exécuter avec Java 1.6 dans la même fenêtre cmd, je commence à obtenir des exceptions:
C:\dev\myapp\src\common\datagen>C:/apps/jdk1.6.0_07/bin/Java.exe -classpath C:\myapp\libs\commons -logging-1.1.jar -server -jar DataGen.jar
Exception in thread "main" Java.lang.NoClassDefFoundError: org/Apache/commons/logging/LogFactory
at com.example.myapp.fomc.common.datagen.DataGenerationTest.<clinit>(Unknown Source)
Caused by: Java.lang.ClassNotFoundException: org.Apache.commons.logging.LogFactory
at Java.net.URLClassLoader$1.run(URLClassLoader.Java:200)
at Java.security.AccessController.doPrivileged(Native Method)
at Java.net.URLClassLoader.findClass(URLClassLoader.Java:188)
at Java.lang.ClassLoader.loadClass(ClassLoader.Java:306)
at Sun.misc.Launcher$AppClassLoader.loadClass(Launcher.Java:276)
at Java.lang.ClassLoader.loadClass(ClassLoader.Java:251)
at Java.lang.ClassLoader.loadClassInternal(ClassLoader.Java:319)
... 1 more
La chose amusante est que la LogFactory incriminée semble être dans commons-logging-1.1.jar, qui se trouve dans le chemin de classe spécifié. Le fichier jar (ouais, c'est vraiment là):
C:\dev\myapp\src\common\datagen>dir C:\myapp\libs\commons-logging-1.1.jar
Volume in drive C is Local Disk
Volume Serial Number is ECCD-A6A7
Directory of C:\myapp\libs
12/11/2007 11:46 AM 52,915 commons-logging-1.1.jar
1 File(s) 52,915 bytes
0 Dir(s) 10,956,947,456 bytes free
Le contenu du fichier commons-logging-1.1.jar:
C:\dev\myapp\src\common\datagen>jar -tf C:\myapp\libs\commons-logging-1.1.jar
META-INF/
META-INF/MANIFEST.MF
org/
org/Apache/
org/Apache/commons/
org/Apache/commons/logging/
org/Apache/commons/logging/impl/
META-INF/LICENSE.txt
META-INF/NOTICE.txt
org/Apache/commons/logging/Log.class
org/Apache/commons/logging/LogConfigurationException.class
org/Apache/commons/logging/LogFactory$1.class
org/Apache/commons/logging/LogFactory$2.class
org/Apache/commons/logging/LogFactory$3.class
org/Apache/commons/logging/LogFactory$4.class
org/Apache/commons/logging/LogFactory$5.class
org/Apache/commons/logging/LogFactory.class
... (more classes in commons-logging-1.1 ...)
Oui, commons-logging a la classe LogFactory. Et enfin, le contenu du manifeste de mon pot:
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.6.5
Created-By: 10.0-b23 (Sun Microsystems Inc.)
Main-Class: com.example.myapp.fomc.common.datagen.DataGenerationTest
Class-Path: commons-logging-1.1.jar commons-lang.jar antlr.jar toplink
.jar GroboTestingJUnit-1.2.1-core.jar junit.jar
Cela m'a laissé perplexe, et tous les collègues que j'ai rencontrés depuis plus d'un jour maintenant. Juste pour cerner les réponses, du moins pour le moment, les solutions tierces à ce problème sont probablement inexpliquées en raison de restrictions en matière de licences et de politiques d'entreprise (par exemple, des outils permettant de créer des exes ou d'emballer des bocaux). Le but ultime est de créer un fichier jar pouvant être copié de mon environnement Windows de développement sur un serveur Linux (avec tous les fichiers jar dépendants) et utilisé pour remplir une base de données (les classpaths peuvent donc être différents entre les environnements de développement et de déploiement). Tout indice sur ce mystère serait grandement apprécié!
L'option -jar est mutuellement exclusive de -classpath. Voir une ancienne description ici
-pot
Exécutez un programme encapsulé dans un fichier JAR. Le premier argument est le nom d'un fichier JAR au lieu d'un nom de classe de démarrage. Pour que cette option fonctionne, le manifeste du fichier JAR doit contenir une ligne de la forme Classe-principale: nom de la classe. Ici, classname identifie la classe ayant la méthode principale publique statique (String [] args) qui sert de point de départ à votre application.
Reportez-vous à la page de référence de l'outil Jar et à la piste Jar du Java Tutorial pour plus d'informations sur l'utilisation des fichiers Jar et des manifestes de fichiers Jar.
Lorsque vous utilisez cette option, le fichier JAR est la source de toutes les classes d'utilisateurs. Les autres paramètres de chemin d'accès aux classes d'utilisateurs sont ignorés.
Un hack rapide et sale consiste à ajouter votre chemin de classe au chemin de classe bootstrap:
-Xbootclasspath/a: chemin
Spécifiez un chemin séparé de deux lignes de directires, archives JAR et archives Zip à ajouter au chemin de classe par défaut bootstrap.
Toutefois, comme @ Dan le dit à juste titre, la solution correcte consiste à vous assurer que le manifeste des fichiers JAR contient le chemin d'accès aux classes pour tous les fichiers JAR dont il aura besoin.
Vous pouvez omettre l'option -jar
et démarrer le fichier jar comme suit:
Java -cp MyJar.jar;C:\externalJars\* mainpackage.MyMainClass
C'est le problème qui se pose,
si le fichier JAR a été chargé à partir de "C:\Java\apps\appli.jar" et que votre fichier manifeste a le chemin d'accès aux classes: référence "lib/other.jar", le chargeur de classes examinera dans "C:\Java\apps\lib\"pour" other.jar ". Il ne regardera pas l'entrée de fichier JAR "lib/other.jar".
Solution:-
[EDIT= La 3ème option génère un dossier en plus du jar, la 2ème option ("Créer les bibliothèques requises dans le JAR généré") peut également être utilisée avec le jar. ]
ouvrez le terminal, indiquez le chemin correct vers votre fichier jar et exécutez-le à l'aide de cette commande Java -jar abc.jar
Maintenant, que va-t-il se passer, le chargeur de classe va chercher dans le bon dossier les fichiers JARS référencés, car ils sont maintenant présents dans le même dossier que celui qui contient votre JAR app ..
Cela a fonctionné pour moi ... J'espère que cela fonctionne pour vous aussi !!!
si vous utilisez des bibliothèques externes dans votre programme et que vous essayez de regrouper tous vos fichiers dans un fichier jar, ce n'est pas si simple, en raison de problèmes de chemin d'accès aux classes, etc.
Je préférerais utiliser OneJar pour ce problème.
j'ai eu le même problème avec mon pot la solution
Manifest-Version: 1.0
Scellé: vrai
Chemin de classe:. lib/jarX1.jar lib/jarX2.jar lib/jarX3.jar
Classe principale: com.MainClass
sélectionner exporter tous les dossiers sortants pour le projet vérifié
Cela a fonctionné pour moi :)
J'ai constaté, lorsque j'utilise un manifeste, que la liste des fichiers jar pour le chemin de classe doit avoir un espace après la liste de chaque fichier, par exemple "requis_lib/Sun/pop3.jar requis_lib/Sun/smtp.jar". Même si c'est le dernier de la liste.