Appelez «java -jar MyFile.jar» avec l’option supplémentaire classpath

J’ai créé un fichier jar contenant tous mes trucs compilés. De plus, mon script de compilation ant copie les bibliothèques requirejses dans un sous-dossier “libs”. La structure ressemble à ceci:

MyProgram.jar libs/ 

Donc, quand j’essaie d’exécuter mon programme maintenant, j’obtiens l’erreur suivante:

 java -cp ".:/home/user/java/MyProgram/jar/libs" -jar MyProgram.jar java.lang.ClassNotFoundException: org.postgresql.Driver 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) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:186) at database.PostgresQL.getConnection(PostgresQL.java:38) at recommender.dao.Creative2IdxDAO.createCreatives2Idx(Creative2IdxDAO.java:19) at main.Main.calculateCorrelationMasortingx(Main.java:51) at main.Main.main(Main.java:28) java.lang.NullPointerException at recommender.dao.Creative2IdxDAO.createCreatives2Idx(Creative2IdxDAO.java:25) at main.Main.calculateCorrelationMasortingx(Main.java:51) at main.Main.main(Main.java:28) 

Pourquoi cela arrive-t-il?

Vous utilisez soit -jar soit -cp , vous ne pouvez pas combiner les deux. Si vous souhaitez append des fichiers JAR supplémentaires sur le chemin de classe, vous devez les placer dans le manifeste du fichier JAR principal, puis utiliser java -jar ou mettre le chemin de classe complet (y compris le fichier JAR principal et ses dépendances) dans -cp et nommer la classe principale. explicitement sur la ligne de commande

 java -cp 'MyProgram.jar:libs/*' main.Main 

(J’utilise la syntaxe dir/* qui indique à la commande java d’append tous .jar fichiers .jar d’un répertoire particulier au classpath. Notez que le * doit être protégé de l’extension par le shell, c’est pourquoi j’ai utilisé single citations.)

Vous mentionnez que vous utilisez Ant pour l’approche manifeste alternative, vous pouvez utiliser la tâche de ant après avoir copié les dépendances mais avant de construire le JAR.

            

Avec ceci en place, java -jar MyProgram.jar fonctionnera correctement et inclura également tous les fichiers JAR libs sur le classpath.

Lorsque l’option -jar est utilisée, l’option -cp est ignorée. Le seul moyen de définir le chemin de classe consiste à utiliser un fichier manifeste dans le fichier jar.

Il est plus facile d’utiliser l’option -cp, d’y append votre fichier jar, puis d’appeler explicitement la classe principale.

En outre, en supposant que le dossier / home / user / java / MyProgram / jar / libs contient des fichiers jar (par opposition aux fichiers de classe), cela ne fonctionnera pas. Vous ne pouvez pas spécifier un dossier de fichier jar mais devez spécifier chaque fichier jar individuellement dans le classpath (cela vaut la peine d’écrire un script shell simple pour le faire s’il y a un nombre important de jars).

C’est un peu difficile. Le script suivant est une tentative pour extraire le chemin de classe du manifeste du fichier jar, puis permettre d’append des entrées de chemin de classe supplémentaires. J’ai eu des résultats mitigés avec cela, mais je veux partager le script, donc il pourrait être entièrement fonctionnel ici.

Le script a deux noms

  • manifester
  • calljar

en reliant les deux fichiers ensemble avec

 ln calljar showmanifest 

avec calljar -h vous pouvez voir l’utilisation.

 #!/bin/bash #set -x # show the manifest of a jar file # 2012-07-18 # author WF # # show usage # usage() { echo "usage: showmanifest (jarfile | directory jarfile) " 1>&2 echo "usage: calljar directory jarfile classpath pattern arguments" 1>&2 echo " -h|--help " 1>&2 echo " show this help and exit" 1>&2 echo " -m|--mainclass javaclass" 1>&2 echo " mainclass to use (otherwise manifest is inspected)" 1>&2 exit 1 } # # show the manifest of the given jar file # show() { dir="$1" jar="$2" fulljar=`find "$dir" -name "$jar"` cd /tmp mkdir show$$ cd show$$ jar xvf $fulljar META-INF/MANIFEST.MF cat META-INF/MANIFEST.MF cd /tmp rm -rf show$$ } # # show the classpath of the manifest # calljar() { dir="$1" jar="$2" classpath="$3" pattern="$4" arguments="$5" cmd=`show "$dir" "$jar" | awk -v extracp="$classpath" -v dir="$dir" -v pattern="$pattern" -v jar="$jar" -v mainclass="$mainclass" -v args="$arguments" ' /Main-Class: / { if (mainclass=="") mainclass=$2 } /^Class-Path:/ { incp=1; cp=$0; gsub("Class-Path: ","",cp) next } /^ .*$/ && incp { line=substr($0,2) # remove carriage return (if any) cp=cp line } END { # we do not like carriage returns gsub("\\r","",cp) gsub("\\r","",mainclass) # we do not like blanks ... gsub(" ","",cp) gsub(pattern,":"dir"/"pattern,cp) print "java -cp " extracp cp ":"dir"/"jar " " mainclass " " args } '` #echo $cmd $cmd } # echo $# arguments found: $* # parse command line options while true; do # echo "option $1" case "$1" in # options without arguments -h|--help) usage;; # for options with required arguments, an additional shift is required -m|--mainclass) mainclass=$2; shift;; (--) shift; break;; (-*) echo "$0: error - unrecognized option $1" 1>&2; usage;; (*) dir=$1;shift;break;; esac shift done #echo "argcount=$#" case $# in 0) dir=`dirname "$dir"` jar=`basename "$dir"` show "$dir" "$jar";; 1) jar="$1" show "$dir" "$jar";; 2) usage;; 3) usage;; *) jar="$1"; shift; classpath="$1"; shift; pattern="$1"; shift; arguments="$@"; #echo "mainclass=${mainclass}" #echo "classpath=${classpath}" #echo calljar "${dir}" "${jar}" "${classpath}" "$pattern" "$arguments" calljar "$dir" "$jar" "$classpath" "$pattern" "$arguments" ;; esac 

Pour des tests rapides et uniques d’une application, vous pouvez simplement créer un lien symbolique entre les fichiers JAR de dépendance nécessaires et le répertoire contenant le fichier JAR de l’application principale.

Exemple (pour une application app.jar qui utilise la bibliothèque SWT d’Eclipse, qui dans mon cas était installée dans /usr/share/java ):

 $ ln -s /usr/share/java/swt.jar . $ java -jar app.jar