Gibt es eine Möglichkeit, alle JAR-Dateien in einem Verzeichnis im Klassenpfad einzuschließen?
Ich versuche Java -classpath lib/*.jar:. my.package.Program
und kann keine Klassendateien finden, die sich mit Sicherheit in diesen Gläsern befinden. Muss ich jede JAR-Datei separat zum Klassenpfad hinzufügen?
Bei Verwendung von Java 6 oder höher unterstützt die Option classpath Platzhalter. Beachte das Folgende:
"
)*
, nicht *.jar
Windows
Java -cp "Test.jar;lib/*" my.package.MainClass
Unix
Java -cp "Test.jar:lib/*" my.package.MainClass
Dies ähnelt Windows, verwendet jedoch :
anstelle von ;
. Wenn Sie keine Platzhalter verwenden können, ermöglicht bash
die folgende Syntax (wobei lib
das Verzeichnis ist, das alle Java Archivdateien enthält):
Java -cp $(echo lib/*.jar | tr ' ' ':')
(Beachten Sie, dass die Verwendung eines Klassenpfads nicht mit der Option -jar
kompatibel ist. Siehe auch: Ausführen einer JAR-Datei mit mehreren Klassenpfadbibliotheken über die Eingabeaufforderung )
Platzhalter verstehen
Aus dem Klassenpfad Dokument:
Klassenpfadeinträge können das Platzhalterzeichen
*
für den Basisnamen enthalten. Dies entspricht der Angabe einer Liste aller Dateien im Verzeichnis mit der Erweiterung.jar
oder.JAR
. Beispielsweise gibt der Klassenpfadeintragfoo/*
alle JAR-Dateien im Verzeichnis foo an. Ein Klassenpfadeintrag, der nur aus*
besteht, wird zu einer Liste aller JAR-Dateien im aktuellen Verzeichnis erweitert.Ein Klassenpfadeintrag, der
*
enthält, stimmt nicht mit Klassendateien überein. Verwenden Sie entwederfoo;foo/*
oderfoo/*;foo
, um Klassen und JAR-Dateien in einem einzigen Verzeichnis abzugleichen. Die gewählte Reihenfolge bestimmt, ob die Klassen und Ressourcen infoo
vor JAR-Dateien infoo
geladen werden oder umgekehrt.Unterverzeichnisse werden nicht rekursiv durchsucht. Beispielsweise sucht
foo/*
nach JAR-Dateien nur infoo
, nicht infoo/bar
,foo/baz
usw.Die Reihenfolge, in der die JAR-Dateien in einem Verzeichnis im erweiterten Klassenpfad aufgelistet werden, ist nicht festgelegt und kann von Plattform zu Plattform und sogar von Moment zu Moment auf demselben Computer variieren. Eine gut konstruierte Anwendung sollte nicht von einer bestimmten Reihenfolge abhängen. Wenn eine bestimmte Reihenfolge erforderlich ist, können die JAR-Dateien im Klassenpfad explizit aufgelistet werden.
Das Erweitern von Platzhaltern erfolgt früh, bevor die Hauptmethode eines Programms aufgerufen wird, und nicht spät, während des Ladevorgangs der Klasse. Jedes Element des Eingabeklassenpfads, das einen Platzhalter enthält, wird durch die (möglicherweise leere) Folge von Elementen ersetzt, die durch Auflisten der JAR-Dateien im angegebenen Verzeichnis generiert wird. Wenn das Verzeichnis
foo
beispielsweisea.jar
,b.jar
undc.jar
enthält, wird der Klassenpfadfoo/*
zufoo/a.jar;foo/b.jar;foo/c.jar
und erweitert Diese Zeichenfolge ist der Wert der SystemeigenschaftJava.class.path
.Die Umgebungsvariable
CLASSPATH
wird nicht anders behandelt als die Befehlszeilenoption-classpath
(oder-cp
). Das heißt, in all diesen Fällen werden Platzhalterzeichen berücksichtigt. Platzhalter für Klassenpfade werden jedoch im HeaderClass-Path jar-manifest
nicht berücksichtigt.
Hinweis: Aufgrund eines bekannten Fehlers in Java 8 müssen die Windows-Beispiele einen Backslash vor den Einträgen mit einem nachgestellten Sternchen verwenden: https://bugs.openjdk.Java.net/browse/JDK -8131329
Unter Windows funktioniert das:
Java -cp "Test.jar;lib/*" my.package.MainClass
und das funktioniert nicht:
Java -cp "Test.jar;lib/*.jar" my.package.MainClass
beachten Sie die * .jar, daher sollte der Platzhalter * allein verwendet werden.
Unter Linux funktioniert Folgendes:
Java -cp "Test.jar:lib/*" my.package.MainClass
Die Trennzeichen sind Doppelpunkte anstelle von Semikolons.
Wir umgehen dieses Problem, indem wir eine main jar-Datei myapp.jar
implementieren, die eine manifest (Manifest.mf
) -Datei enthält, die einen Klassenpfad mit den anderen erforderlichen Jars angibt , die dann daneben eingesetzt werden. In diesem Fall müssen Sie nur Java -jar myapp.jar
deklarieren, wenn Sie den Code ausführen.
Wenn Sie also das Hauptverzeichnis jar
in einem Verzeichnis bereitstellen und dann die abhängigen Gläser in einen Ordner lib
darunter legen, sieht das Manifest folgendermaßen aus:
Manifest-Version: 1.0
Implementation-Title: myapp
Implementation-Version: 1.0.1
Class-Path: lib/dep1.jar lib/dep2.jar
NB: Dies ist plattformunabhängig - wir können dieselben JARs zum Starten auf einem UNIX-Server oder einem Windows-PC verwenden.
Meine Lösung unter Ubuntu 10.04 mit Java-Sun 1.6.0_24 mit allen Jars im "lib" -Verzeichnis:
Java -cp .: lib/* my.main.Class
Wenn dies fehlschlägt, sollte der folgende Befehl funktionieren (druckt alle * .jars im lib-Verzeichnis in den classpath-Parameter)
Java -cp $ (für i in lib/*. Jar; do echo -n $ i:; done). meine.Hauptklasse
Bei mir funktioniert das unter Windows.
Java -cp "/lib/*;" sample
Für Linux
Java -cp "/lib/*:" sample
Ich benutze Java 6
Kurze Antwort: Java -classpath lib/*:. my.package.Program
Oracle bietet Dokumentation zur Verwendung von Platzhaltern in Klassenpfaden hier für Java 6 und hier für Java 7 unter der Abschnittsüberschrift Grundlegendes zu Platzhaltern für Klassenpfade . (Während ich das schreibe, enthalten die beiden Seiten dieselben Informationen.) Hier eine Zusammenfassung der Highlights:
Um alle JARs in ein bestimmtes Verzeichnis aufzunehmen, können Sie im Allgemeinen den Platzhalter *
( not *.jar
) verwenden. .
Der Platzhalter stimmt nur mit JARs überein, nicht mit Klassendateien. Um alle Klassen in einem Verzeichnis abzurufen, beenden Sie einfach den Klassenpfad-Eintrag am Verzeichnisnamen.
Die beiden oben genannten Optionen können kombiniert werden, um alle JAR- und Klassendateien in einem Verzeichnis einzuschließen. Dabei gelten die üblichen Regeln für die Priorität von Klassenpfaden. Z.B. -cp /classes;/jars/*
Der Platzhalter sucht nicht nach JARs in Unterverzeichnissen.
Die obigen Punkte gelten, wenn Sie die Systemeigenschaft CLASSPATH
oder die Befehlszeilenflags -cp
oder -classpath
verwenden. Wenn Sie jedoch den JAR-Manifest-Header Class-Path
verwenden (wie bei einer Ant-Build-Datei), werden Platzhalter nicht berücksichtigt.
Ja, mein erster Link ist derselbe, der in der Antwort mit der höchsten Punktzahl angegeben wurde (von der ich keine Hoffnung habe, ihn zu überholen), aber diese Antwort bietet nur wenige Erklärungen über den Link hinaus. Da diese Art von Verhalten entmutigt bei Stapelüberlauf heutzutage ist, dachte ich, ich würde es erweitern.
Sie können Java -Djava.ext.dirs=jarDirectory
http://docs.Oracle.com/javase/6/docs/technotes/guides/extensions/spec.html versuchen
Verzeichnis für externe Jars unter Java
Windows:
Java -cp file.jar;dir/* my.app.ClassName
Linux:
Java -cp file.jar:dir/* my.app.ClassName
Erinnern:
- Windows Pfadtrennzeichen ist ;
- Linux Pfadtrennzeichen ist :
- Wenn das Argument cp unter Windows keine Leerzeichen enthält, sind die "Anführungszeichen" optional
Richtig:
Java -classpath "lib/*:." my.package.Program
Falsch:
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
Wenn Sie wirklich alle .jar-Dateien dynamisch angeben müssen, können Sie Shell-Skripte oder Apache Ant verwenden. Es gibt ein Commons-Projekt mit dem Namen Commons Launcher , mit dem Sie Ihr Startskript im Grunde als Ant-Build-Datei angeben können (wenn Sie sehen, was ich meine).
Dann können Sie Folgendes angeben:
<path id="base.class.path">
<pathelement path="${resources.dir}"/>
<fileset dir="${extensions.dir}" includes="*.jar" />
<fileset dir="${lib.dir}" includes="*.jar"/>
</path>
In Ihrer Starterstellungsdatei, die Ihre Anwendung mit dem richtigen Klassenpfad startet.
Wenn Sie Java 6 verwenden, können Sie Platzhalter im Klassenpfad verwenden.
Jetzt ist es möglich, Platzhalter in der Klassenpfaddefinition zu verwenden:
javac -cp libs/* -verbose -encoding UTF-8 src/mypackage/*.Java -d build/classes
Beachten Sie, dass die Platzhaltererweiterung für Java 7 unter Windows nicht funktioniert.
Lesen Sie dieses StackOverflow-Problem , um weitere Informationen zu erhalten.
Die Problemumgehung besteht darin, direkt nach dem Platzhalter ein Semikolon einzufügen. Java -cp "somewhere/*;"
Wen es angeht,
Ich fand dieses seltsame Verhalten unter Windows unter einer MSYS/MinGW-Shell.
Works:
$ javac -cp '.;c:\Programs\COMSOL44\plugins\*' Reclaim.Java
Funktioniert nicht:
$ 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
Ich bin mir ziemlich sicher, dass der Platzhalter von der Shell nicht erweitert wird, weil z.
$ echo './*'
./*
(Versuchte es auch mit einem anderen Programm, anstatt mit dem eingebauten echo
, mit dem gleichen Ergebnis.)
Ich glaube, es ist javac
, das versucht, es zu erweitern, und es verhält sich anders, ob das Argument ein Semikolon enthält oder nicht. Zunächst wird möglicherweise versucht, alle Argumente zu erweitern, die wie Pfade aussehen. Und nur dann würde es sie analysieren, wobei -cp
nur das folgende Token entgegennimmt. (Beachten Sie, dass com.comsol.aco_1.0.0.jar
die zweite JAR in diesem Verzeichnis ist.) Das ist alles eine Vermutung.
Das ist
$ javac -version
javac 1.7.0
Für Windows sind Anführungszeichen erforderlich und; sollte als Trennzeichen verwendet werden. z.B.:
Java -cp "target\\*;target\\dependency\\*" my.package.Main
Kurzform: Befindet sich Ihr Hauptverzeichnis in einem Jar, benötigen Sie wahrscheinlich einen zusätzlichen '-jar pathTo/yourJar/YourJarsName.jar', der explizit deklariert wurde, damit es funktioniert (obwohl sich 'YourJarsName.jar' im Klassenpfad befand) (oder , ausgedrückt, um die ursprüngliche Frage zu beantworten, die vor 5 Jahren gestellt wurde: Sie müssen nicht jedes Glas explizit neu deklarieren, aber es scheint, dass Sie auch mit Java6 Ihr eigenes Glas neu deklarieren müssen ...)
Lange Form: (Ich habe dies explizit gemacht, so dass ich hoffe, dass auch Eindringlinge von Java Gebrauch machen können)
Wie viele hier verwende ich Eclipse zum Exportieren von JARs: (Datei-> Exportieren -> 'Runnable JAR File'). Es gibt drei Optionen für die Bibliotheksverwaltung, die Eclipse (Juno) bietet:
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"
Normalerweise würde ich opt2 verwenden (und opt1 war definitiv fehlerhaft), aber in einem der von mir verwendeten Jars habe ich Fehler mit dem praktischen "jarinjar" -Trick entdeckt, den Eclipse nutzt, wenn Sie diese Option auswählen. Selbst nachdem mir klar wurde, dass ich opt3 brauchte und dann diesen StackOverflow-Eintrag fand, brauchte ich einige Zeit, um herauszufinden, wie ich mein Hauptprogramm außerhalb von Eclipse starten konnte.
Wenn Sie Ihr jar benannt haben: "fooBarTheJarFile.jar" und alles so eingestellt ist, dass es in das Verzeichnis exportiert wird: "/ theFully/qualifiedPath/toYourChosenDir".
(Das bedeutet, dass das Feld "Ziel exportieren" lautet: "/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile.jar".)
Nachdem Sie auf "Fertig stellen" geklickt haben, werden in Eclipse alle Bibliotheken in einem Ordner mit dem Namen "fooBarTheJarFile_lib" in diesem Exportverzeichnis abgelegt.
/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
Sie können dann von überall auf Ihrem System starten mit:
Java -classpath "/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile_lib/*" -jar /theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile.jar package.path_to.the_class_with.your_main.TheClassWithYourMain
(Für Java Newbies: 'package.path_to.the_class_with.your_main' ist der deklarierte Paketpfad, den Sie oben in der 'TheClassWithYourMain.Java'-Datei finden, die das' main (String [ ] args) {...} ', die Sie von außerhalb von Java ausführen möchten)
Zu bemerken ist, dass die Angabe von 'fooBarTheJarFile.jar' in der Liste der Jars in Ihrem deklarierten Klassenpfad nicht ausreicht. Sie müssen explizit '-jar' deklarieren und den Speicherort dieses Jars neu deklarieren.
z.B. das bricht:
Java -classpath "/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile.jar;/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile_lib/*" somepackages.inside.yourJar.leadingToTheMain.TheClassWithYourMain
angepasst mit relativen Pfaden:
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
(mit Java Version "1.6.0_27"; über OpenJDK 64-Bit-Server VM unter Ubuntu 12.04)
Alle oben genannten Lösungen funktionieren hervorragend, wenn Sie die Anwendung Java außerhalb von IDE wie Eclipse oder Netbeans entwickeln und ausführen.
Wenn Sie unter Windows 7 Eclipse IDE für die Entwicklung in Java verwenden, treten möglicherweise Probleme auf, wenn Sie die in Eclipse erstellten Klassendateien mit der Eingabeaufforderung ausführen.
Z.B. Ihr Quellcode in Eclipse hat die folgende Pakethierarchie: edu.sjsu.myapp.Main.Java
Sie haben json.jar als externe Abhängigkeit für Main.Java
Wenn Sie versuchen, Main.Java in Eclipse auszuführen, wird es ohne Probleme ausgeführt.
Aber wenn Sie versuchen, dies mit der Eingabeaufforderung auszuführen, nachdem Sie Main.Java in Eclipse kompiliert haben, werden einige seltsame Fehler mit der Meldung "ClassNotDef Error blah blah" ausgegeben.
Ich nehme an, Sie befinden sich im Arbeitsverzeichnis Ihres Quellcodes !!
Verwenden Sie die folgende Syntax, um sie an der Eingabeaufforderung auszuführen:
javac -cp ".; json.jar" Main.Java
Java -cp ".; json.jar" edu.sjsu.myapp.Main
Verpassen Sie nicht die. über]
Dies liegt daran, dass Sie Main.Java im Paket edu.sjsu.myapp platziert haben und Java.exe nach dem genauen Muster sucht.
Ich hoffe es hilft !!
Ich weiß nur, wie ich es individuell machen kann, zum Beispiel:
setenv CLASSPATH /User/username/newfolder/jarfile.jar:jarfile2.jar:jarfile3.jar:.
Ich hoffe, das hilft!
klasse von 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
Keine direkte Lösung, um/* auf -cp setzen zu können, aber ich hoffe, Sie könnten das folgende Skript verwenden, um die Situation für dynamische Klassenpfade und lib-Verzeichnisse ein wenig zu vereinfachen.
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;
Skript für Linux, könnte auch für Windows ein ähnliches haben. Wenn das richtige Verzeichnis als Eingabe für "libDir2Scan4jars" bereitgestellt wird; Das Skript durchsucht alle Jars und erstellt einen Klassenpfad-String und exportiert ihn in eine Umgebungsvariable "tmpCLASSPATH".
Stellen Sie den Klassenpfad so ein, dass er für mehrere Jars und die Klassendateien des aktuellen Verzeichnisses geeignet ist.
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
Sie müssen sie alle separat hinzufügen. Alternativ können Sie, wenn Sie wirklich nur ein Verzeichnis angeben müssen, alles in einem Verzeichnis entpacken und dem Klassenpfad hinzufügen. Ich empfehle diesen Ansatz jedoch nicht, da Sie bizarre Probleme bei der Versionierung von Klassenpfaden und bei der Unverwaltbarkeit riskieren.
Stellen Sie sich eine JAR-Datei als Stamm einer Verzeichnisstruktur vor. Ja, Sie müssen alle separat hinzufügen.
Ich habe mehrere Gläser in einem Ordner. Der folgende Befehl funktionierte für mich in JDK1.8
, um alle im Ordner vorhandenen Gläser einzuschließen. Bitte beachten Sie, dass in Anführungszeichen eingeschlossen werden muss, wenn der Klassenpfad ein Leerzeichen enthält
Windows
Kompilieren: javac -classpath "C:\My Jars\sdk\lib\*" c:\programs\MyProgram.Java
Laufen: Java -classpath "C:\My Jars\sdk\lib\*;c:\programs" MyProgram
Linux
Kompilieren: javac -classpath "/home/guestuser/My Jars/sdk/lib/*" MyProgram.Java
Laufen: Java -classpath "/home/guestuser/My Jars/sdk/lib/*:/home/guestuser/programs" MyProgram
Ich versuche, Java als jar oder als Klassen in Ubuntu auszuführen. Ich habe bei beiden Optionen versagt. Die folgende Ausnahme ist die Ausgabe.
Download link: https://upload.cat/f694139f88c663b1
Java org.statmetrics.Statmetric
oder
Java -cp /home/elias/statmetrics/statmetrics.jar :. org.statmetrics.Statmetrics
oder
Java-Klassenpfad "/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
Ich habe die Antwort gefunden:
Meine Dummheit.
Erster Schritt: Sie müssen das entsprechende Java einstellen: Ich hatte Java 11, aber ich habe als Java lib Pfad die 8. Version eingestellt! - Hier können Sie die Java -Version einstellen:
Sudo update-alternatives --config Java
2. Schritt: Führen Sie dann den folgenden Befehl aus, indem Sie Pfad- und Dateinamen in den entsprechenden Pfad und die entsprechenden Dateien ändern:
Java -classpath "/usr/lib/jvm/Java-1.8.0-openjdk-AMD64/jre/lib/*" -jar /home/elias/statmetrics/statmetrics.jar org.statmetrics.Statmetrics
Es wurde erfolgreich gelaufen!