Вопрос-ответ

Including all the jars in a directory within the Java classpath

Включение всех jar в каталог в пределах пути к классу Java

Есть ли способ включить все файлы jar в каталоге в classpath?

Я пытаюсь java -classpath lib/*.jar:. my.package.Program и не могу найти файлы классов, которые определенно находятся в этих jar. Нужно ли мне добавлять каждый jar-файл в classpath отдельно?

Переведено автоматически
Ответ 1

При использовании Java 6 или более поздней версии параметр classpath поддерживает подстановочные знаки. Обратите внимание на следующее:


  • Используйте прямые кавычки (")

  • Использовать *, а не *.jar

Windows


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


Unix


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


Это похоже на Windows, но использует : вместо ;. Если вы не можете использовать подстановочные знаки, bash допускается следующий синтаксис (где lib - каталог, содержащий все файлы архива Java):


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


(Обратите внимание, что использование classpath несовместимо с -jar опцией. Смотрите также: Выполнить jar-файл с несколькими библиотеками classpath из командной строки)

Понимание подстановочных знаков

Из документа Classpath:


Записи пути к классу могут содержать подстановочный знак basename *, который считается эквивалентным указанию списка всех файлов в каталоге с расширением .jar или .JAR. Например, запись пути к классу foo/* указывает все JAR-файлы в каталоге с именем foo. Запись classpath, состоящая просто из *, расширяется до списка всех jar-файлов в текущем каталоге.


Запись пути к классу, которая содержит *, не будет соответствовать файлам класса. Чтобы сопоставить оба класса и JAR-файлы в одном каталоге foo, используйте или foo;foo/* или foo/*;foo. Выбранный порядок определяет, загружаются ли классы и ресурсы в foo перед файлами JAR в foo, или наоборот.


Рекурсивный поиск в подкаталогах не выполняется. Например, foo/* ищет JAR-файлы только в foo, а не в foo/bar, foo/baz и т.д.


Порядок, в котором JAR-файлы в каталоге перечисляются в расширенном пути к классу, не указан и может варьироваться от платформы к платформе и даже от момента к моменту на одном и том же компьютере. Хорошо сконструированное приложение не должно зависеть от какого-либо определенного порядка. Если требуется определенный порядок, файлы JAR могут быть явно перечислены в пути к классу.


Расширение подстановочных знаков выполняется заранее, до вызова основного метода программы, а не позже, во время самого процесса загрузки класса. Каждый элемент входного пути к классу, содержащий подстановочный знак, заменяется (возможно, пустой) последовательностью элементов, сгенерированной путем перечисления JAR-файлов в именованном каталоге. Например, если каталог foo содержит a.jar, b.jar, и c.jar, то путь к классу foo/* расширяется в foo/a.jar;foo/b.jar;foo/c.jar, и эта строка будет значением системного свойства java.class.path.


CLASSPATH Переменная среды обрабатывается таким же образом, как и параметр -classpath (или -cp) командной строки. То есть во всех этих случаях используются подстановочные знаки. Однако подстановочные знаки пути к классу не учитываются в Class-Path jar-manifest заголовке.


Примечание: из-за известной ошибки в java 8, в примерах Windows перед записями должна использоваться обратная косая черта со звездочкой в конце: https://bugs.openjdk.java.net/browse/JDK-8131329

Ответ 2

В Windows это работает:

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

и это не работает:

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

Обратите внимание на *.jar, поэтому подстановочный знак * следует использовать отдельно.


В Linux работает следующее:

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

Разделителями являются двоеточия вместо точки с запятой.

Ответ 3

Мы решаем эту проблему путем развертывания основного jar-файла, myapp.jar который содержит файл манифеста (Manifest.mf), указывающий путь к классу, с другими необходимыми jar-файлами, которые затем развертываются вместе с ним. В этом случае вам нужно только объявить java -jar myapp.jar при запуске кода.

Итак, если вы развернете main jar в некоторый каталог, а затем поместите зависимые jar-файлы в lib папку под ним, манифест будет выглядеть следующим образом:

Manifest-Version: 1.0
Implementation-Title: myapp
Implementation-Version: 1.0.1
Class-Path: lib/dep1.jar lib/dep2.jar

ПРИМЕЧАНИЕ: это не зависит от платформы - мы можем использовать одни и те же jar-файлы для запуска на сервере UNIX или на ПК с Windows.

Ответ 4

Мое решение в Ubuntu 10.04 с использованием java-sun 1.6.0_24, имеющее все банки в каталоге "lib":

java -cp .:lib/* my.main.Класс

Если это не удается, должна сработать следующая команда (выводит все * .jar в каталоге lib с параметром classpath)

java -cp $(для i в lib /*.jar ; выполнить echo -n $ i : ; готово). my.main.Класс
java