Est-il possible d'inclure tous les fichiers jar dans un répertoire du chemin d'accès aux classes?
J'essaie Java -classpath lib/*.jar:. my.package.Program
et il n'est pas en mesure de trouver des fichiers de classe qui se trouvent certainement dans ces fichiers. Dois-je ajouter chaque fichier JAR au classpath séparément?
En utilisant Java 6 ou version ultérieure, l'option classpath prend en charge les caractères génériques. Notez les points suivants:
"
)*
et non *.jar
Windows
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 tous les fichiers d'archive Java):
Java -cp $(echo lib/*.jar | tr ' ' ':')
(Notez que l'utilisation d'un chemin d'accès aux classes est incompatible avec l'option -jar
. Voir aussi: Exécuter le fichier jar avec plusieurs bibliothèques de chemins d'accès aux classes à partir de la commande Invite )
Comprendre les caractères génériques
Depuis le Classpath document:
Les entrées de chemin d'accès aux classes peuvent contenir le caractère générique de nom de base
*
, ce qui revient à spécifier une liste de tous les fichiers du répertoire portant l'extension.jar
ou.JAR
. Par exemple, l'entrée du chemin de classefoo/*
spécifie tous les fichiers JAR du répertoire nommé foo. Une entrée de chemin de classe consistant simplement en*
se développe en une liste de tous les fichiers jar du répertoire en cours.Une entrée de chemin de classe contenant
*
ne correspondra pas aux fichiers de classe. Pour faire correspondre les classes et les fichiers JAR dans un même répertoire foo, utilisezfoo;foo/*
oufoo/*;foo
. L'ordre choisi détermine si les classes et les ressources dansfoo
sont chargées avant les fichiers JAR dansfoo
, ou inversement.Les sous-répertoires ne sont pas recherchés de manière récursive. Par exemple,
foo/*
ne recherche les fichiers JAR que dansfoo
, pas dansfoo/bar
,foo/baz
, etc.L'ordre dans lequel les fichiers JAR d'un répertoire sont énumérés dans le chemin de classe développé n'est pas spécifié et peut varier d'une plateforme à l'autre et même d'un instant à l'autre sur le même ordinateur. Une application bien construite ne doit dépendre d'aucun ordre particulier. 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 est effectuée tôt, avant l'invocation de la méthode principale d'un programme, plutôt que tardivement, pendant le processus de chargement de classe lui-même. Chaque élément du chemin de classe en entrée contenant un caractère générique est remplacé par la séquence d'éléments (éventuellement vide) générée en énumérant les fichiers JAR du répertoire nommé. Par exemple, si le répertoire
foo
contienta.jar
,b.jar
etc.jar
, 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
). Autrement dit, les caractères génériques sont respectés dans tous ces cas. Toutefois, les caractères génériques du chemin de classe ne sont pas respectés dans l'en-têteClass-Path jar-manifest
.
Remarque: en raison d'un bogue connu dans Java 8, les exemples de Windows doivent utiliser une barre oblique inverse précédant les entrées suivies d'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
remarquez le * .jar, le caractère générique * doit donc ê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 principalmyapp.jar
qui contient un fichier manifeste (Manifest.mf
) spécifiant un chemin d'accès aux classes avec les autres fichiers jars requis. , qui sont ensuite déployés à ses côtés. Dans ce cas, il vous suffit de déclarer Java -jar myapp.jar
lors de l'exécution du code.
Ainsi, si vous déployez le fichier jar
principal dans un répertoire, puis que vous placez les fichiers JAR dépendants dans un dossier lib
situé en dessous, le manifeste se présente comme suit:
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 fichiers JAR pour les lancer sur un serveur UNIX ou sur un PC Windows.
Ma solution sur Ubuntu 10.04 utilisant Java-Sun 1.6.0_24 ayant tous les fichiers JAR dans le répertoire "lib":
Java -cp.: Lib/* my.main.Class
Si cela échoue, la commande suivante devrait fonctionner (affiche tous les fichiers * .jars du répertoire lib dans le paramètre classpath)
Java -cp $ (pour i dans lib/*. Jar; echo -n $ i:; done). my.main.Class
Pour moi, cela fonctionne dans les fenêtres.
Java -cp "/lib/*;" sample
Pour linux
Java -cp "/lib/*:" sample
J'utilise Java 6
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 classes ici pour Java 6 et ici pour Java 7 , sous le titre de la section Comprendre les caractères génériques du chemin de classe . (Au moment où j'écris ces lignes, les deux pages contiennent les mêmes informations.) Voici un résumé des points saillants:
En général, pour inclure tous les fichiers JAR dans un répertoire donné, vous pouvez utiliser le caractère générique *
( et non *.jar
). .
Le caractère générique correspond uniquement aux fichiers JAR, pas aux fichiers de classe; pour obtenir toutes les classes d'un répertoire, il suffit de terminer l'entrée de classpath par le nom du répertoire.
Les deux options ci-dessus peuvent être combinées pour inclure tous les fichiers JAR et de classe dans un répertoire. Les règles de priorité de chemin d'accès aux classes habituelles s'appliquent. Par exemple. -cp /classes;/jars/*
Le caractère générique ne recherchera pas les fichiers JAR dans les sous-répertoires.
Les points ci-dessus sont vrais si vous utilisez la propriété système CLASSPATH
ou les indicateurs de ligne de commande -cp
ou -classpath
. Toutefois, si vous utilisez l'en-tête du manifeste JAR Class-Path
(comme vous le feriez avec un fichier de construction ant), les caractères génériques ne seront pas pas .
Oui, mon premier lien est identique à celui indiqué 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'explications au-delà du lien. Étant donné que ce type de comportement est déconseillé sur Stack Overflow ces jours-ci , je pensais que je l'étendrais davantage.
Vous pouvez essayer Java -Djava.ext.dirs=jarDirectory
http://docs.Oracle.com/javase/6/docs/technotes/guides/extensions/spec.html
Répertoire des fichiers jar externes lors de l'exécution de Java
Windows:
Java -cp file.jar;dir/* my.app.ClassName
Linux:
Java -cp file.jar:dir/* my.app.ClassName
Rappeler:
- Windows le séparateur de chemin est ;
- Linux le séparateur de chemin est :
- Sous Windows, si l'argument cp ne contient pas d'espace blanc, les "guillemets" sont facultatifs.
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
Si vous devez vraiment spécifier tous les fichiers .jar de manière dynamique, vous pouvez utiliser des scripts Shell ou Apache Ant . Il existe un projet commun appelé Commons Launcher qui vous permet 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, ce qui lancera votre application avec le bon chemin de classe.
Si vous utilisez Java 6, vous pouvez utiliser des caractères génériques dans le chemin d'accès aux classes.
Il est maintenant possible d'utiliser des caractères génériques dans la définition du chemin de classe:
javac -cp libs/* -verbose -encoding UTF-8 src/mypackage/*.Java -d build/classes
Veuillez noter que le développement de caractères génériques est interrompu pour Java 7 sous Windows.
Consultez ce problème de StackOverflow pour plus d'informations.
La solution de contournement consiste à mettre un point-virgule juste après le caractère générique. Java -cp "somewhere/*;"
À qui cela concerne,
J'ai trouvé ce comportement étrange sur Windows sous un shell MSYS/MinGW.
Works:
$ 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 à peu près 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'élargir, et il se comporte différemment, qu'il y ait un point-virgule dans l'argument ou non. Premièrement, il peut être tentant d’élargir tous les arguments qui ressemblent à des chemins. Et alors seulement, il les analyserait, avec -cp
prenant uniquement le jeton suivant. (Notez que com.comsol.aco_1.0.0.jar
est le deuxième fichier JAR de ce répertoire.) C'est une supposition.
C'est
$ javac -version
javac 1.7.0
Pour Windows, des guillemets sont requis et; devrait être utilisé comme séparateur. par exemple.:
Java -cp "target\\*;target\\dependency\\*" my.package.Main
Short Form: Si votre main est dans un jar, vous aurez probablement besoin d'un '-jar pathTo/yourJar/YourJarsName.jar' supplémentaire explicitement déclaré pour le faire fonctionner (même si 'YourJarsName.jar' était sur le chemin de la classe) (ou , exprimé pour répondre à la question initiale qui avait été posée il y a 5 ans: vous n'avez pas besoin de redéclarer chaque pot de manière explicite, mais il semble que même avec Java6 vous ayez besoin de redéclarer votre propre pot ...)
Forme longue: (j'ai expliqué cela au point que j'espère que même les intrus à Java pourront en profiter)
Comme beaucoup ici, j'utilise Eclipse pour exporter des fichiers JAR: (Fichier-> Exporter -> 'Fichier JAR exécutable'). Eclipse (Juno) offre trois options:
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"
En général, j'utilisais opt2 (et opt1 était définitivement en train de casser), mais le code natif de l'un des bocaux que j'utilise a découvert des ruptures avec le truc "jarinjar" bien pratique qu'Eclipse tire parti de cette option. Même après avoir réalisé que j'avais besoin de opt3, puis avoir trouvé cette entrée StackOverflow, il m'a fallu un peu de temps pour comprendre comment lancer mon environnement principal hors d'Eclipse. Voici donc ce qui a fonctionné pour moi, car il est utile pour les autres ...
Si vous avez nommé votre fichier jar: "fooBarTheJarFile.jar" et que tout est configuré pour exporter vers le répertoire: "/ theFully/competentPath/toYourChosenDir".
(Cela signifie que le champ "Destination de l'exportation" se lit comme suit: "/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile.jar")
Une fois que vous avez terminé, vous trouverez qu'Eclipse place toutes les bibliothèques dans un dossier nommé 'fooBarTheJarFile_lib' situé dans ce répertoire d'exportation, ce qui vous donne 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 depuis 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 Java Newbies: 'package.path_to.the_class_with.your_main' est le chemin indiqué dans le package que vous trouverez en haut du fichier 'TheClassWithYourMain.Java' contenant le 'main ( ] args) {...} 'que vous souhaitez exécuter en dehors de Java)
Le piège à noter est qu’avoir "fooBarTheJarFile.jar" dans la liste des fichiers jar de votre chemin de classe déclaré n’est pas suffisant. Vous devez déclarer explicitement '-jar' et redéclarer l'emplacement de ce fichier .jar.
par exemple. cela casse:
Java -classpath "/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile.jar;/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile_lib/*" somepackages.inside.yourJar.leadingToTheMain.TheClassWithYourMain
retraité avec les 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
(avec Java version "1.6.0_27"; via un serveur OpenJDK 64 bits VM sur Ubuntu 12.04)
Toutes les solutions ci-dessus fonctionnent parfaitement si vous développez et exécutez l'application Java en dehors de tout IDE comme Eclipse ou Netbeans.
Si vous utilisez Windows 7 et utilisez Eclipse IDE pour le développement en Java, vous pouvez rencontrer des problèmes si vous utilisez Invite de commande pour exécuter les fichiers de classe intégrés à Eclipse.
Par exemple. Votre code source dans Eclipse présente la hiérarchie de packages suivante: edu.sjsu.myapp.Main.Java
Vous avez json.jar comme dépendance externe pour le fichier Main.Java
Lorsque vous essayez d'exécuter Main.Java à partir d'Eclipse, celui-ci s'exécutera sans problème.
Mais lorsque vous essayez d'exécuter cette commande à l'aide de l'invite de commandes après la compilation de Main.Java dans Eclipse, des erreurs étranges sont générées, telles que "ClassNotDef Error blah blah".
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 la commande Invite:
javac -cp ".; json.jar" Main.Java
Java -cp ".; json.jar" edu.sjsu.myapp.Main
[Ne manquez pas le. au dessus de]
En effet, vous avez placé Main.Java dans le package edu.sjsu.myapp et Java.exe recherchera le modèle exact.
J'espère que ça aide !!
La seule façon dont je sais comment faire est de le faire individuellement, par exemple:
setenv CLASSPATH /User/username/newfolder/jarfile.jar:jarfile2.jar:jarfile3.jar:.
J'espère que ça t'as aidé!
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
Ce n’est pas une solution directe pour pouvoir définir/* sur -cp, mais j’espère que vous pourrez utiliser le script suivant pour faciliter un peu la situation concernant 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 en avoir un similaire pour Windows. Si le répertoire approprié est fourni en entrée dans "libDir2Scan4jars"; le script analysera tous les fichiers jar, créera une chaîne de chemin de classe et l'exportera dans une variable env "tmpCLASSPATH".
Définissez le chemin de classe de manière appropriée pour plusieurs fichiers JAR et les fichiers de classe du répertoire en cours.
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
Vous devez les ajouter tous séparément. Alternativement, si vous vraiment devez simplement spécifier un répertoire, vous pouvez tout détourner dans un répertoire et l'ajouter à votre chemin de classe. Je ne recommande toutefois pas cette approche, car vous risquez des problèmes bizarres en matière de gestion de version de chemins d'accès aux classes et d'inviolabilité.
Pensez à un fichier jar en tant que racine d'une structure de répertoires. Oui, vous devez tous les ajouter séparément.
J'ai plusieurs bocaux dans un dossier. La commande ci-dessous a fonctionné pour moi dans JDK1.8
pour inclure tous les fichiers JAR présents dans le dossier. S'il vous plaît noter que pour inclure des guillemets si vous avez un espace dans le classpath
Windows
Compilation: javac -classpath "C:\My Jars\sdk\lib\*" c:\programs\MyProgram.Java
En cours d'exécution: Java -classpath "C:\My Jars\sdk\lib\*;c:\programs" MyProgram
Linux
Compilation: javac -classpath "/home/guestuser/My Jars/sdk/lib/*" MyProgram.Java
En cours d'exécution: Java -classpath "/home/guestuser/My Jars/sdk/lib/*:/home/guestuser/programs" MyProgram
J'essaie de lancer le fichier Java en tant que jar ou en tant que classes dans Ubuntu. J'ai échoué dans les deux options. L'exception suivante est sa sortie.
Download link: https://upload.cat/f694139f88c663b1
Java org.statmetrics.Statmetric
ou
Java -cp /home/elias/statmetrics/statmetrics.jar :. org.statmetrics.Statmetrics
ou
Java -classpath "/usr/lib/jvm/Java-1.8.0-openjdk-AMD64/jre/lib/*" -jar /home/elias/statmeics/statmetrics.jar org.statmetrics.Statmetrics
Exception in thread "Thread-0" Java.lang.NoClassDefFoundError: javax/xml/bind/annotation/adapters/XmlAdapter
at Java.base/Java.lang.ClassLoader.defineClass1(Native Method)
at Java.base/Java.lang.ClassLoader.defineClass(ClassLoader.Java:1016)
at Java.base/Java.security.SecureClassLoader.defineClass(SecureClassLoader.Java:174)
at Java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.Java:802)
at Java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.Java:700)
at Java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.Java:623)
at Java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.Java:581)
at Java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.Java:178)
at Java.base/Java.lang.ClassLoader.loadClass(ClassLoader.Java:521)
at org.statmetrics.c.a(Unknown Source)
at org.statmetrics.dw.a(Unknown Source)
at org.statmetrics.dx.run(Unknown Source)
Caused by: Java.lang.ClassNotFoundException: javax.xml.bind.annotation.adapters.XmlAdapter
at Java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.Java:583)
at Java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.Java:178)
at Java.base/Java.lang.ClassLoader.loadClass(ClassLoader.Java:521)
... 12 more
J'ai trouvé la réponse:
Ma bêtise.
Première étape: vous devez définir le code Java correspondant: j’avais Java 11 mais j’ai défini comme chemin Java lib la 8e version! - Vous pouvez définir la version Java à partir d'ici:
Sudo update-alternatives --config Java
2ème étape: Exécutez ensuite la commande suivante, en modifiant le chemin et les noms de fichiers en fichiers et chemins correspondants:
Java -classpath "/usr/lib/jvm/Java-1.8.0-openjdk-AMD64/jre/lib/*" -jar /home/elias/statmetrics/statmetrics.jar org.statmetrics.Statmetrics
C'était couru avec succès!