1186 Stimmen

Einbindung aller Jars in einem Verzeichnis in den Java-Klassenpfad

Gibt es eine Möglichkeit, alle JAR-Dateien innerhalb eines Verzeichnisses in den Klassenpfad aufzunehmen?

Ich versuche java -classpath lib/*.jar:. my.package.Program und es ist nicht in der Lage, Klassendateien zu finden, die in diesen Jars enthalten sind. Muss ich jede Jar-Datei separat zum Klassenpfad hinzufügen?

1323voto

basszero Punkte 29038

Bei Verwendung von Java 6 oder höher unterstützt die Option classpath Wildcards. Beachten Sie das Folgende:

  • Verwenden Sie gerade Anführungszeichen ( " )
  • Verwenden Sie * , nicht *.jar

Windows

java -cp "Test.jar;lib/*" my.package.MainClass

Unix

java -cp "Test.jar:lib/*" my.package.MainClass

Dies ist ähnlich wie bei Windows, verwendet aber : 代わりに ; . Wenn Sie keine Platzhalter verwenden können, bash erlaubt die folgende Syntax (wobei lib ist das Verzeichnis, das alle Java-Archivdateien enthält):

java -cp "$(printf %s: lib/*.jar)"

(Beachten Sie, dass die Verwendung eines Klassenpfads nicht mit dem -jar Option. Siehe auch: Jar-Datei mit mehreren Klassenpfadbibliotheken von der Eingabeaufforderung aus ausführen )

Verstehen von Platzhaltern

De la Klassenpfad Dokument:

Klassenpfadeinträge können das Platzhalterzeichen für den Basisnamen enthalten * was gleichbedeutend mit der Angabe einer Liste aller Dateien ist in dem Verzeichnis mit der Erweiterung .jar o .JAR . Zum Beispiel kann der Klassenpfad-Eintrag foo/* spezifiziert alle JAR-Dateien in dem Verzeichnis foo. Ein Klassenpfadeintrag, der einfach aus * erweitert sich zu einer Liste mit allen der jar-Dateien im aktuellen Verzeichnis.

Ein Klassenpfadeintrag, der Folgendes enthält * passt nicht zu Klassendateien. Um sowohl Klassen als auch JAR-Dateien in einem einzigen Verzeichnis foo abzugleichen, verwenden Sie entweder foo;foo/* o foo/*;foo . Die gewählte Reihenfolge bestimmt, ob die Klassen und Ressourcen in foo werden vor JAR-Dateien in foo , oder andersherum.

Unterverzeichnisse werden nicht rekursiv durchsucht. Zum Beispiel, foo/* siehe nach JAR-Dateien nur in foo , nicht in foo/bar , foo/baz etc.

Die Reihenfolge, in der die JAR-Dateien in einem Verzeichnis im erweiterten Klassenpfad aufgezählt werden erweiterten Klassenpfad aufgezählt werden, ist nicht festgelegt und kann von Plattform zu Plattform und sogar von Moment zu Moment auf demselben Rechner variieren. A gut konstruierte Anwendung sollte nicht von einer bestimmten Reihenfolge abhängen. Wenn eine bestimmte Reihenfolge erforderlich ist, können die JAR-Dateien explizit im Klassenpfad aufgezählt werden.

Die Expansion von Platzhaltern erfolgt früh, vor dem Aufruf einer der Hauptmethode eines Programms und nicht erst während des Ladens der Klasse Prozess selbst. Jedes Element des Eingabeklassenpfads, das einen Wildcard enthält, wird durch die (möglicherweise leere) Folge von Elementen ersetzt, die durch Aufzählung der JAR-Dateien im benannten Verzeichnis erzeugt wird. Für zum Beispiel, wenn das Verzeichnis foo enthält a.jar , b.jar y c.jar dann der Klassenpfad foo/* wird erweitert zu foo/a.jar;foo/b.jar;foo/c.jar , und diese Zeichenkette wäre der Wert der Systemeigenschaft java.class.path .

El CLASSPATH wird nicht anders behandelt als die Umgebungsvariable der -classpath (oder -cp ) Befehlszeilenoption. Das heißt, Wildcards werden in all diesen Fällen beachtet. Allerdings werden Platzhalter für Klassenpfade nicht in der Option Class-Path jar-manifest Kopfzeile.

Hinweis: Aufgrund eines bekannten Fehlers in Java 8 muss in den Windows-Beispielen ein Backslash vor den Einträgen mit einem Sternchen am Ende stehen: https://bugs.openjdk.java.net/browse/JDK-8131329

280voto

davorp Punkte 3906

Unter Windows funktioniert dies:

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 das Folgende:

java -cp "Test.jar:lib/*" my.package.MainClass

Die Abscheider sind Doppelpunkte 代わりに Semikolons .

76voto

oxbow_lakes Punkte 131223

Wir umgehen dieses Problem durch den Einsatz eines principal jar-Datei myapp.jar die eine Manifest ( Manifest.mf ), in der ein Klassenpfad mit den anderen erforderlichen Jars angegeben ist, die dann zusammen mit der Datei bereitgestellt werden. In diesem Fall müssen Sie nur deklarieren java -jar myapp.jar bei der Ausführung des Codes.

Wenn Sie also die Haupt jar in ein beliebiges Verzeichnis und dann die abhängigen Jars in ein lib Darunter sieht das Manifest wie folgt 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 die gleichen Jars verwenden, um auf einem UNIX-Server oder einem Windows-PC zu starten.

54voto

Habi Punkte 529

Meine Lösung auf Ubuntu 10.04 mit java-sun 1.6.0_24 mit allen jars in "lib" Verzeichnis:

java -cp .:lib/\* my.main.Class

Wenn dies fehlschlägt, sollte der folgende Befehl funktionieren (gibt alle *.jars im lib-Verzeichnis in den Klassenpfad-Parameter aus)

java -cp $(for i in lib/\*.jar ; do echo -n $i: ; done). my.main.Class

48voto

Pops Punkte 29149

Kurze Antwort: java -classpath lib/*:. my.package.Program

Oracle bietet eine Dokumentation zur Verwendung von Wildcards in Klassenpfaden hier für Java 6 y hier für Java 7 unter der Überschrift Verstehen von Klassenpfad-Platzhaltern . (

  • Um alle JARs in einem bestimmten Verzeichnis einzuschließen, können Sie im Allgemeinen den Platzhalter * ( no *.jar ).

  • Der Platzhalter passt nur auf JARs, nicht auf Klassendateien; um alle Klassen in einem Verzeichnis zu erhalten, beenden Sie den Klassenpfadeintrag einfach mit dem Verzeichnisnamen.

  • Die beiden oben genannten Optionen können kombiniert werden, um alle JAR- und Klassendateien in einem Verzeichnis einzuschließen, und es gelten die üblichen Vorrangregeln für den Klassenpfad. z.B. -cp /classes;/jars/*

  • Der Platzhalter wird no Suche nach JARs in Unterverzeichnissen.

  • Die obigen Aufzählungspunkte gelten, wenn Sie die CLASSPATH Systemeigenschaft oder die -cp o -classpath Befehlszeilen-Flags. Wenn Sie jedoch die Class-Path JAR-Manifest-Header (wie Sie es mit einer Ant-Build-Datei tun könnten), werden Wildcards no geehrt werden.

Ja, mein erster Link ist derselbe, der in der Antwort mit der höchsten Punktzahl angegeben ist (die ich nicht überholen kann), aber diese Antwort enthält außer dem Link keine weiteren Erklärungen. Da diese Art von Verhalten entmutigt auf Stack Overflow in diesen Tagen dachte ich mir, dass ich das noch weiter ausführe.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X