Inclure tous les fichiers jar dans un répertoire dans le classpath Java
Est-il un moyen d'inclure tous les fichiers jar dans un répertoire dans le chemin de classe?
J'essaie java -classpath lib/*.jar:. my.package.Program
et il n'est pas capable de trouver des fichiers de classe qui sont certainement dans ces pots. Dois-je ajouter chaque fichier jar au chemin de classe séparément?
22 answers
En utilisant Java 6 ou version ultérieure, l'option classpath prend en charge les caractères génériques. Notez ce qui suit:
- Utiliser des guillemets droits (
"
) - Utilisez
*
, pas*.jar
Les fenêtres
java -cp "Test.jar;lib/*" my.package.MainClass
Unix
java -cp "Test.jar:lib/*" my.package.MainClass
Ceci est similaire à Windows, mais utilise :
au lieu de ;
. Si vous ne pouvez pas utiliser de caractères génériques, bash
autorise la syntaxe suivante (où lib
est le répertoire contenant Fichiers d'archives Java):
java -cp $(echo lib/*.jar | tr ' ' ':')
(Notez que l'utilisation d'un chemin de classe est incompatible avec l'option -jar
. Voir aussi: Exécuter le fichier jar avec plusieurs classpath bibliothèques à partir de l'invite de commande)
Comprendre les caractères génériques
Du document Classpath :
Les entrées de chemin de classe peuvent contenir le caractère générique basename
*
, ce qui est considéré comme équivalent à spécifier une liste de tous les fichiers dans le répertoire avec l'extension.jar
ou.JAR
. Par exemple, l' l'entrée de chemin de classefoo/*
spécifie tous les fichiers JAR dans le répertoire nommé foo. Une entrée classpath composée simplement de*
se développe en une liste de tous les fichiers jar dans le répertoire courant.Une entrée de chemin de classe qui contient
*
ne correspondra pas aux fichiers de classe. De faites correspondre les deux classes et les fichiers JAR dans un seul répertoire foo, utilisez soitfoo;foo/*
oufoo/*;foo
. L'ordre choisi détermine si le les classes et les les ressources dansfoo
sont chargées avant les fichiers JAR dansfoo
, ou inversement.Les sous-répertoires ne sont pas recherchés récursivement. Par exemple,
foo/*
regarde pour les fichiers JAR uniquement dansfoo
, pas dansfoo/bar
,foo/baz
, etc.L'ordre dans lequel les fichiers JAR d'un répertoire sont élargi la catégorie chemin n'est pas spécifié et peut varier d'une plateforme à plate-forme, et même d'un moment à l'autre sur la même machine. Un une application bien construite ne doit pas dépendre tout particulier ordre. Si un ordre spécifique est requis les fichiers JAR peuvent être énumérés explicitement dans le chemin de classe.
L'expansion des caractères génériques se fait tôt, avant l'invocation d'un méthode principale du programme, plutôt que tardive, pendant le chargement de la classe le processus lui-même. Chaque élément du chemin de classe d'entrée contenant un le caractère générique est remplacé par la séquence (éventuellement vide) d'éléments généré en énumérant les fichiers JAR dans le répertoire nommé. Pour exemple, si le répertoire
foo
contienta.jar
,b.jar
, etc.jar
, alors le chemin de classefoo/*
est développé enfoo/a.jar;foo/b.jar;foo/c.jar
, et cette chaîne serait la valeur de la propriété systèmejava.class.path
.La variable d'environnement
CLASSPATH
n'est pas traitée différemment de l'option de ligne de commande-classpath
(ou-cp
). Qui est, les jokers sont à l'honneur dans tous ces cas. Cependant, les caractères génériques de chemin de classe ne sont pas honoré dans l'en-têteClass-Path jar-manifest
.
Remarque: en raison d'un bogue connu dans java 8, le les exemples Windows doivent utiliser une barre oblique inverse précédant les entrées avec un astérisque de fin: https://bugs.openjdk.java.net/browse/JDK-8131329
Sous Windows, cela fonctionne:
java -cp "Test.jar;lib/*" my.package.MainClass
Et cela ne fonctionne pas:
java -cp "Test.jar;lib/*.jar" my.package.MainClass
Notez le *.jar, donc le caractère générique * doit être utilisé seul.
Sous Linux, les travaux suivants:
java -cp "Test.jar:lib/*" my.package.MainClass
Les séparateurs sont des deux-points au lieu de points-virgules.
Nous contournons ce problème en déployant un fichier jar main myapp.jar
qui contient un manifeste (Manifest.mf
) fichier spécifiant un chemin de classe avec les autres fichiers jar requis, qui sont ensuite déployés à côté de celui-ci. Dans ce cas, il vous suffit de déclarer java -jar myapp.jar
lors de l'exécution du code.
Donc, si vous déployez le jar
principal dans un répertoire, puis placez les fichiers jar dépendants dans un dossier lib
en dessous, le manifeste ressemble à:
Manifest-Version: 1.0
Implementation-Title: myapp
Implementation-Version: 1.0.1
Class-Path: lib/dep1.jar lib/dep2.jar
NB: ceci est indépendant de la plateforme - nous pouvons utiliser les mêmes jars pour lancer sur un serveur UNIX ou sur un PC Windows.
Ma solution sur Ubuntu 10.04 en utilisant java-sun 1.6.0_24 ayant tous les pots dans le répertoire "lib":
java -cp .:lib/* my.main.Class
Si cela échoue, la commande suivante devrait fonctionner (affiche tout*.jars dans le répertoire lib au paramètre classpath)
java -cp $(for i in lib/*.jar ; do echo -n $i: ; done). my.main.Class
Réponse courte: java -classpath lib/*:. my.package.Program
Oracle fournit de la documentation sur l'utilisation de caractères génériques dans les chemins de classeici pour Java 6 etici pour Java 7 , sous l'en-tête de sectionComprendre les caractères génériques de chemin de classe . (Au moment où j'écris ceci, les deux pages contiennent les mêmes informations.) Voici un résumé des faits saillants:
En général, pour inclure tous les Bocaux dans un répertoire donné, vous pouvez utiliser le caractère générique
*
(pas*.jar
).Le caractère générique ne correspond qu'aux fichiers JAR, pas aux fichiers de classe; pour obtenir toutes les classes dans un répertoire, terminez simplement l'entrée classpath au nom du répertoire.
Les deux options ci-dessus peuvent être combinées pour inclure tous les fichiers JAR et class dans un répertoire, et les règles de priorité classpath habituelles s'appliquent. Par exemple.
-cp /classes;/jars/*
Le caractère générique ne recherche pas les fichiers JAR dans les sous-répertoires.
Les puces ci-dessus sont vraies si vous utilisez le
CLASSPATH
propriété système ou les indicateurs de ligne de commande-cp
ou-classpath
. Cependant, si vous utilisez l'en-tête du manifeste JARClass-Path
(comme vous pouvez le faire avec un fichier de construction ant), les caractères génériques ne seront pas honorés.
Oui, mon premier lien est le même que celui fourni dans la réponse la mieux notée (que je n'ai aucun espoir de dépasser), mais cette réponse ne fournit pas beaucoup d'explication au-delà du lien. Depuis ce genre de comportement est découragé sur un Débordement de Pile ces jours - , Je pensais étendre sur elle.
Pour moi, cela fonctionne sous Windows .
java -cp "/lib/*;" sample
Pour linux
java -cp "/lib/*:" sample
Je suis l'aide de Java 6
Vous pouvez essayer java -Djava.ext.dirs=jarDirectory
http://docs.oracle.com/javase/6/docs/technotes/guides/extensions/spec.html
Répertoire pour les fichiers jar externes lors de l'exécution de java
Corriger:
java -classpath "lib/*:." my.package.Program
Incorrect:
java -classpath "lib/a*.jar:." my.package.Program
java -classpath "lib/a*:." my.package.Program
java -classpath "lib/*.jar:." my.package.Program
java -classpath lib/*:. my.package.Program
Windows:
java -cp fichier.jar; dir / * mon.App.className
Linux:
java -cp fichier.jar: dir / * mon.App.className
Rappeler:
- Windows séparateur de chemin est ";"
- Linux séparateur de chemin est ":"
- Dans Windows si l'argument cp ne contient pas d'espace blanc, les "guillemets" sont facultatifs
Si vous avez vraiment besoin de spécifier tous les .fichiers jar dynamiquement, vous pouvez utiliser des scripts shell, ou Apache Ant . Il existe un projet commons appelé Commons Launcher qui vous permet essentiellement de spécifier votre script de démarrage en tant que fichier de construction ant (si vous voyez ce que je veux dire).
Ensuite, vous pouvez spécifier quelque chose comme:
<path id="base.class.path">
<pathelement path="${resources.dir}"/>
<fileset dir="${extensions.dir}" includes="*.jar" />
<fileset dir="${lib.dir}" includes="*.jar"/>
</path>
Dans votre fichier de construction de lancement, qui lancera votre application avec le chemin de classe correct.
Si vous utilisez Java 6, vous pouvez utiliser des caractères génériques dans le chemin de classe.
Maintenant, il est possible d'utiliser des caractères génériques dans la définition de classpath:
javac -cp libs/* -verbose -encoding UTF-8 src/mypackage/*.java -d build/classes
Veuillez noter que l'extension générique est interrompue pour Java 7 sous Windows.
Consultez ce problème StackOverflow pour plus d'informations.
La solution consiste à mettre un point-virgule juste après le caractère générique. java -cp "somewhere/*;"
À qui cela peut concerner,
J'ai trouvé ce comportement étrange sous Windows sous un shell MSYS/MinGW.
Œuvres:
$ javac -cp '.;c:\Programs\COMSOL44\plugins\*' Reclaim.java
Ne fonctionne pas:
$ javac -cp 'c:\Programs\COMSOL44\plugins\*' Reclaim.java
javac: invalid flag: c:\Programs\COMSOL44\plugins\com.comsol.aco_1.0.0.jar
Usage: javac <options> <source files>
use -help for a list of possible options
Je suis tout à fait sûr que le caractère générique n'est pas développé par le shell, car par exemple
$ echo './*'
./*
(Essayé avec un autre programme aussi, plutôt que le echo
intégré, avec le même résultat.)
Je crois que c'est javac
qui essaie de l'étendre, et il se comporte différemment s'il y a est un point-virgule dans l'argument ou pas. Tout d'abord, il peut essayer d'étendre tous les arguments qui ressemblent à des chemins. Et seulement alors il les analyserait, avec -cp
ne prenant que le jeton suivant. (Notez que com.comsol.aco_1.0.0.jar
est le deuxième JAR de ce répertoire.) C'est tout une supposition.
C'est
$ javac -version
javac 1.7.0
Toutes les solutions ci-dessus fonctionnent très bien si vous développez et exécutez l'application Java en dehors de toutE comme Eclipse ou Netbeans.
Si vous utilisez Windows 7 et utilisez Eclipse ID pour le développement en Java, vous pouvez rencontrer des problèmes si vous utilisez l'invite de commande pour exécuter les fichiers de classe construits dans Eclipse.
Par exemple, votre code source dans Eclipse a la hiérarchie de paquets suivante: edu.sjsu.myapp.Principal.java
Vous avez json.bocal comme une dépendance externe pour le Principal.java
Lorsque vous essayez d'exécuter Main.java à partir d'Eclipse, il fonctionnera sans aucun problème.
Mais lorsque vous essayez de l'exécuter à l'aide de l'invite de commande après la compilation de Main.java dans Eclipse, il va tirer quelques erreurs étranges disant "Erreur ClassNotDef bla bla".
Je suppose que vous êtes dans le répertoire de travail de votre code source !!
Utilisez la syntaxe suivante pour l'exécuter à partir de l'invite de commande:
Javac -cp ".; json.jar " Principal.java
-
Java -cp ".; json.jar" edu.sjsu.myapp.Principal
[Ne manquez pas le . ci-dessus]
C'est parce que vous avez placé le Principal.java dans le paquet edu.sjsu.myapp et java.exe recherchera le modèle exact.
J'espère que ça aide !!
Pour Windows, les guillemets sont requis et ; doit être utilisé comme séparateur. par exemple:
java -cp "target\\*;target\\dependency\\*" my.package.Main
Forme courte: Si votre main est dans un jar, vous aurez probablement besoin d'un chemin '-jar supplémentaire pour/yourJar/YourJarsName.jar 'explicitement déclaré pour le faire fonctionner (même si' YourJarsName.jar ' était sur le chemin de classe) (ou, exprimé pour répondre à la question originale qui a été posée il y a 5 ans: vous n'avez pas besoin de redéclarer explicitement chaque pot, mais semble, même avec java6, vous devez redéclarer votre propre pot ...)
Formulaire long: (J'ai rendu cela explicite au point que j'espère même les interlopers vers java peuvent utiliser ceci)
Comme beaucoup ici, j'utilise eclipse pour exporter des pots: (Fichier->Exporter> > 'Fichier JAR exécutable'). Il existe trois options sur la gestion de la bibliothèque eclipse (Juno):
opt1: "Extract required libraries into generated JAR"
opt2: "Package required libraries into generated JAR"
opt3: "Copy required libraries into a sub-folder next to the generated JAR"
Typiquement, j'utiliserais opt2 (et opt1 cassait définitivement), mais le code natif dans l'un des pots que j'utilise, j'ai découvert des ruptures avec l'astuce pratique "jarinjar" qu'eclipse exploite lorsque vous choisissez cette option. Même après avoir réalisé que j'avais besoin d'opt3, puis trouver ceci Entrée StackOverflow, il m'a encore fallu un certain temps pour comprendre comment lancer mon principal en dehors d'eclipse, alors voici ce qui a fonctionné pour moi, car c'est utile pour les autres...
Si vous avez nommé votre pot: "fooBarTheJarFile.pot" et tout est configuré pour exporter vers le répertoire: "/ theFully/qualifiedPath / toYourChosenDir".
(ce qui signifie que le champ 'Export destination' se lira: '/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile.jar')
Après avoir touché finish, vous trouverez eclipse place ensuite toutes les bibliothèques dans un dossier nommé 'fooBarTheJarFile_lib' dans ce répertoire d'exportation, vous donnant quelque chose comme:
/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile.jar
/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile_lib/SomeOtherJar01.jar
/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile_lib/SomeOtherJar02.jar
/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile_lib/SomeOtherJar03.jar
/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile_lib/SomeOtherJar04.jar
Vous pouvez ensuite lancer de n'importe où sur votre système avec:
java -classpath "/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile_lib/*" -jar /theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile.jar package.path_to.the_class_with.your_main.TheClassWithYourMain
(Pour les débutants Java: 'package.chemin_to.the_class_with.your_main ' est le chemin de paquet déclaré que vous trouverez en haut de 'TheClassWithYourMain.java fichier qui contient le main(String[] args){...} 'que vous souhaitez courir de l'extérieur java)
L'écueil à remarquer: est que d'avoir 'fooBarTheJarFile.jar ' dans la liste des jars sur votre chemin de classe déclaré ne suffit pas. Vous devez déclarer explicitement '- jar' et redéclarer l'emplacement de ce jar.
Par exemple, cela casse:
java -classpath "/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile.jar;/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile_lib/*" somepackages.inside.yourJar.leadingToTheMain.TheClassWithYourMain
Reformulé avec des chemins relatifs:
cd /theFully/qualifiedPath/toYourChosenDir/;
BREAKS: java -cp "fooBarTheJarFile_lib/*" package.path_to.the_class_with.your_main.TheClassWithYourMain
BREAKS: java -cp ".;fooBarTheJarFile_lib/*" package.path_to.the_class_with.your_main.TheClassWithYourMain
BREAKS: java -cp ".;fooBarTheJarFile_lib/*" -jar package.path_to.the_class_with.your_main.TheClassWithYourMain
WORKS: java -cp ".;fooBarTheJarFile_lib/*" -jar fooBarTheJarFile.jar package.path_to.the_class_with.your_main.TheClassWithYourMain
(en utilisant la version java "1.6.0_27"; via OpenJDK 64-Bit Server VM sur ubuntu 12.04)
La seule façon dont je sais comment est de le faire individuellement, par exemple:
setenv CLASSPATH /User/username/newfolder/jarfile.jar:jarfile2.jar:jarfile3.jar:.
J'espère que ça aide!
Classe de wepapp:
> mvn clean install
> java -cp "webapp/target/webapp-1.17.0-SNAPSHOT/WEB-INF/lib/tool-jar-1.17.0-SNAPSHOT.jar;webapp/target/webapp-1.17.0-SNAPSHOT/WEB-INF/lib/*" com.xx.xx.util.EncryptorUtils param1 param2
Pas une solution directe pour pouvoir définir /* sur-cp mais j'espère que vous pourriez utiliser le script suivant pour faciliter un peu la situation pour les chemins de classe dynamiques et les répertoires lib.
libDir2Scan4jars="../test";cp=""; for j in `ls ${libDir2Scan4jars}/*.jar`; do if [ "$j" != "" ]; then cp=$cp:$j; fi; done; echo $cp| cut -c2-${#cp} > .tmpCP.tmp; export tmpCLASSPATH=`cat .tmpCP.tmp`; if [ "$tmpCLASSPATH" != "" ]; then echo .; echo "classpath set, you can now use ~> java -cp \$tmpCLASSPATH"; echo .; else echo .; echo "Error please check libDir2Scan4jars path"; echo .; fi;
Scripté pour Linux, pourrait avoir un similaire pour Windows aussi. Si le répertoire approprié est fourni en entrée dans le "libDir2Scan4jars" ; le script analysera tous les fichiers jar et créera une chaîne classpath et l'exportera vers une variable env"tmpCLASSPATH".
Vous devez tous les ajouter séparément. Alternativement, si vous vraiment devez simplement spécifier un répertoire, vous pouvez tout ajouter dans un répertoire et l'ajouter à votre chemin de classe. Je ne recommande cependant pas cette approche car vous risquez des problèmes bizarres dans la gestion des versions de classpath et l'ingérable.
Considérez un fichier jar comme la racine d'une structure de répertoires. Oui, vous devez les ajouter tous séparément.
Définissez le chemin de classe d'une manière appropriée plusieurs fichiers jar et les fichiers de classe du répertoire courant.
CLASSPATH=${ORACLE_HOME}/jdbc/lib/ojdbc6.jar:${ORACLE_HOME}/jdbc/lib/ojdbc14.jar:${ORACLE_HOME}/jdbc/lib/nls_charset12.jar;
CLASSPATH=$CLASSPATH:/export/home/gs806e/tops/jconn2.jar:.;
export CLASSPATH