Incluant tous les pots dans un répertoire dans le classpath Java
y a-t-il un moyen d'inclure tous les fichiers jar dans un répertoire dans classpath?
j'essaie java -classpath lib/*.jar:. my.package.Program
et il n'est pas en mesure de trouver les fichiers de classe qui sont certainement dans ces pots. Dois-je ajouter chaque fichier jar séparément dans classpath?
22 réponses
en utilisant Java 6 ou plus tard, l'option classpath supporte les caractères génériques. Note ce qui suit:
- utilisez des guillemets (
"
) - utiliser
*
, pas*.jar
Windows
java -cp "Test.jar;lib/*" my.package.MainClass
Unix
java -cp "Test.jar:lib/*" my.package.MainClass
c'est similaire à Windows, mais utilise :
au lieu de ;
. Si vous ne pouvez pas utiliser les caractères génériques, bash
permet la syntaxe suivante (où lib
est le répertoire contenant tous les 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 un fichier jar avec plusieurs bibliothèques classpath à partir de l'invite de commande )
La Compréhension Des Caractères Génériques
De la Classpath document:
les entrées de chemin de classe peuvent contenir le caractère de caractère de base
*
, 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 consistant simplement en*
s'étend à une liste de tous les les fichiers jar dans le répertoire courant.une entrée de chemin de classe qui contient
Les sous-répertoires*
ne correspond pas aux fichiers de classe. De faites correspondre les deux classes et les fichiers JAR dans un seul répertoire foo, utilisez l'une ou l'autrefoo;foo/*
oufoo/*;foo
. L'ordre choisi détermine si le les classes et ressources dansfoo
sont chargées avant les fichiers JAR dansfoo
, ou inversement.ne font pas l'objet d'une recherche récursive. Par exemple,
foo/*
semble pour les fichiers JAR uniquement dansfoo
, pas dansfoo/bar
,foo/baz
, etc.L'ordre dans lequel les fichiers JAR dans un répertoire sont énumérés dans la é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 devrait pas dépendre d'une ordre. Si une commande spécifique est nécessaire, alors les fichiers JAR peuvent être énumérés explicitement dans le chemin de classe.
L'extension de wildcards 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 joker, c'est remplacé par la séquence d'éléments (éventuellement vide) 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
, puis le chemin de classefoo/*
est élargi enfoo/a.jar;foo/b.jar;foo/c.jar
, et cette chaîne serait la valeur de la propriété du systèmejava.class.path
.la variable d'environnement
CLASSPATH
n'est pas traitée de manière différente de le-classpath
(ou-cp
) option en ligne de commande. Qui est, les jokers sont à l'honneur dans tous ces cas. Cependant, les jokers de chemin de classe ne sont pas honoré dans l'en-têteClass-Path jar-manifest
.
Note: en raison d'un bug connu dans java 8, les exemples de windows doivent utiliser un antislash précédent les entrées avec un astérisque de fuite: 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
avis *.jar, donc le Joker * doit être utilisé seul .
sur Linux, les travaux suivants:
java -cp "Test.jar:lib/*" my.package.MainClass
les séparateurs sont des colons au lieu de point-virgule.
nous contournons ce problème en déployant un fichier main jar file myapp.jar
qui contient un fichier manifest ( Manifest.mf
) spécifiant un chemin de classe avec les autres jarres requises, qui sont ensuite déployées à ses côtés. Dans ce cas, vous n'avez qu'à déclarer java -jar myapp.jar
lors de l'exécution du code.
donc si vous déployez le principal jar
dans un répertoire, et puis mettre les pots dépendants dans un lib
dossier 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 plate-forme - nous pouvons utiliser les mêmes bocaux pour lancer sur un serveur UNIX ou sur un PC Windows.
Ma solution sur Ubuntu 10.04 à l'aide de java-sun 1.6.0_24 avoir tous les pots dans "lib":
java -cp .:lib/* my.main.Class
Si cela échoue, la commande suivante devrait fonctionner (imprime tous *.les bocaux dans le répertoire lib du classpath param)
java -cp $(for i in lib/*.jar ; do echo -n $i: ; done). my.main.Class
courte réponse: java -classpath lib/*:. my.package.Program
Oracle fournit de la documentation sur l'utilisation de caractères génériques dans les classpaths ici pour Java 6 et ici pour Java 7 , sous la rubrique comprendre les caractères génériques de classe . (Au moment où j'écris ces lignes, les deux pages contiennent la même information.) Voici un résumé des faits saillants:
-
en général, comprend tous les biens suivants: les pots dans un répertoire donné, vous pouvez utiliser le Joker
*
( pas*.jar
). -
le Joker ne correspond qu'à des jarres, pas à des fichiers de classe; pour obtenir toutes les classes dans un répertoire, il suffit de terminer 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 habituelles de priorité classpath appliquer. Par exemple:
-cp /classes;/jars/*
-
Le caractère générique pas recherche pour les Bocaux dans des sous-répertoires.
-
les points de puce ci-dessus sont vrais si vous utilisez la propriété de système
CLASSPATH
ou les drapeaux de ligne de commande-cp
ou-classpath
. Cependant, si vous utilisez l'en-têteClass-Path
jar manifest (comme vous pourriez le faire avec un fichier ANT build), les caractères génériques seront Non soit honoré.
Oui, mon premier lien est le même que celui fourni dans la réponse la mieux cotée (que je n'ai aucun espoir de dépasser), mais cette réponse ne fournit pas beaucoup d'explications au-delà du lien. Puisque ce genre de comportement est découragé sur le débordement de la pile ces jours , j'ai pensé que je voudrais développer sur elle.
vous pouvez essayer java -Djava.ext.dirs=jarDirectory
http://docs.oracle.com/javase/6/docs/technotes/guides/extensions/spec.html
Répertoire externe pots lors de l'exécution de java
Correct :
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/* mes.App.Nom de la classe
Linux :
java -cp fichier.jar:dir/* mes.App.Nom de la classe
rappeler:
- Windows séparateur de chemin est" ; "
- Linux séparateur de chemin d'accès est " : "
- Dans Windows si l'argument cp ne contient pas d'espace blanc, le " guillemets "est optionnel
Si vous avez vraiment besoin de spécifier tous les .fichiers jar dynamiquement, vous pouvez utiliser des scripts shell, ou Apache Ant . Il y a un projet commun appelé Commons Launcher qui vous permet essentiellement de spécifier votre script de démarrage comme un fichier de construction ant (si vous voyez ce que je veux dire).
alors, 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 corriger classpath.
si vous utilisez Java 6, Vous pouvez utiliser des caractères génériques dans classpath.
il est maintenant 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 Joker est cassée pour Java 7 sous Windows.
Check out ce StackOverflow question pour plus d'informations.
La solution est de mettre un point-virgule juste après le générique. java -cp "somewhere/*;"
à qui de droit,
j'ai trouvé ce comportement étrange sur Windows sous un shell MSYS/MinGW.
:
$ 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 Joker n'est pas étendu par le shell, parce que par exemple
$ echo './*'
./*
(essayé avec un autre programme aussi, plutôt que le intégré echo
, avec le même résultat.)
je crois que c'est javac
qui essaie de l'étendre, et il se comporte différemment qu'il y ait ou non un point-virgule dans l'argument. Tout d'abord, il peut essayer d'étendre tous les arguments qui ressemblent à des chemins. Et c'est seulement alors qu'il les analyserait, avec -cp
ne prenant que le symbole suivant. (Notez que com.comsol.aco_1.0.0.jar
est le deuxième JAR dans ce répertoire.) C'est 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 tout IDE comme Eclipse ou Netbeans.
si vous êtes sur Windows 7 et que vous utilisez Eclipse IDE pour le développement en Java, vous pourriez rencontrer des problèmes si vous utilisez L'invite de commande pour exécuter les fichiers de classe construits à L'intérieur D'Eclipse.
E. G. Votre code source dans Eclipse a la hiérarchie de paquet suivante:: edu.sjsu.myapp.Principal.java
vous avez json.bocal comme une dépendance externe pour le Principal.java
quand vous essayez de lancer Main.java depuis Eclipse, elle fonctionnera sans problèmes.
mais quand vous essayez d'exécuter ceci en utilisant la commande invite après avoir compilé Main.java dans Eclipse, il va tirer un peu bizarre erreurs en disant: "ClassNotDef Erreur 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.Main
[ne manquez pas le . ci-dessus]
C'est parce que vous avez placé principal.de java à l'intérieur du paquet edu.sjsu.myapp et java.exe va chercher le modèle exact.
Espère que cela aide !!
Pour windows, les guillemets doivent être utilisés comme séparateurs. par exemple:
java -cp "target\*;target\dependency\*" my.package.Main
forme courte: si votre main est dans un pot, vous aurez probablement besoin d'un '-jar pathTo/yourJar/YourJarsName.jar 'a explicitement déclaré de le faire fonctionner (même si' YourJarsName.pot' était sur le chemin de la 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 re-écl arer chaque pot explicitement, mais ne semble, même avec java6, vous avez besoin de re-écl arer votre propre pot ...)
Forme Longue: (J'ai fait cette explicites au point que j'ai de l'espoir, même intrus à java pouvez utiliser ceci)
comme beaucoup ici j'utilise eclipse pour exporter des jarres: (File->Export-->'Runnable JAR File'). Il y a trois options sur les offres 'Library handling' 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 était définitivement en train de casser), cependant le code natif dans l'un des bocaux que j'utilise j'ai découvert des ruptures avec le trick "jarinjar" très pratique qui permet d'éclipser les leviers lorsque vous choisissez cette option. Même après avoir réalisé que j'avais besoin de l'opt3, et trouver cette entrée StackOverflow, il m'a fallu un certain temps pour comprendre comment lancer mon main en dehors d'eclipse, donc voici ce qui a fonctionné pour moi, car il est utile pour d'autres...
si vous avez nommé votre pot: "fooBarTheJarFile.pot" et tout est réglé pour exporter vers le dir: "/ theFully/qualifiedPath / toYourChosenDir".
(C'est-à-dire le le champ "destination" se lira comme suit: "/theFully/qualifiedPath/toYourChosenDir / fooBarTheJarFile.jar')
après que vous ayez appuyé sur finish, vous trouverez eclipse qui place 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 alors lancer à partir 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 En Java: ".path_to.the_class_with.your_main ' est le chemin de paquet déclaré que vous trouverez en haut du 'TheClassWithYourMain'.le fichier java 'qui contient le' main (String[] args){...}' que vous souhaitez exécuter à partir de l'extérieur de java)
le piège à remarquer: est celui ayant 'fooBarTheJarFile.jar " dans la liste des pots sur votre déclarée classpath n'est pas assez. Vous devez déclarer explicitement '-pot", et redeclare l'emplacement de ce pot.
p.ex. ceci casse:
java -classpath "/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile.jar;/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile_lib/*" somepackages.inside.yourJar.leadingToTheMain.TheClassWithYourMain
reformulé avec les trajectoires relatives:
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
(utilisant la version java" 1.6.0_27"; via OpenJDK 64-Bit Server VM sur ubuntu 12.04)
la seule façon que je connaisse est de le faire individuellement, par exemple:
setenv CLASSPATH /User/username/newfolder/jarfile.jar:jarfile2.jar:jarfile3.jar:.
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
N'est pas une solution directe à la possibilité de définir /* to-cp mais j'espère que vous pouvez utiliser le script suivant pour faciliter un peu la situation pour les chemins de classes 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 comme entrée dans les "libDir2Scan4jars", le script va scanner tous les jarres et créer une chaîne classpath et l'exporter vers une variable env"tmpCLASSPATH".
vous devez les ajouter tous séparément. Sinon, si vous vraiment avez juste besoin de spécifier un répertoire, vous pouvez tout déballer dans un dir et ajouter cela à votre classpath. Je ne recommande pas cette approche, cependant, car vous risquez des problèmes bizarres de versioning classpath et d'ingérable.
pense à un fichier jar comme la racine d'une structure de répertoire. Oui, vous devez ajouter tous séparément.
définit le chemin de classe d'une manière appropriée plusieurs pots 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