Включение всех jar-файлов в каталог внутри Java classpath - PullRequest
926 голосов
/ 20 октября 2008

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

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

Ответы [ 24 ]

1065 голосов
/ 21 октября 2008

Используя 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 $(echo lib/*.jar | tr ' ' ':')

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

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

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

Записи пути к классу могут содержать подстановочный знак базового имени *, что считается эквивалентным указанию списка всех файлов в каталоге с расширением .jar или .JAR. Например, Запись пути к классам foo/* определяет все файлы JAR в каталоге с именем Foo. Запись пути к классу, состоящая просто из *, расширяется до списка всех файлы 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

216 голосов
/ 14 августа 2009

Под окнами это работает:

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

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

63 голосов
/ 21 октября 2008

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

Таким образом, если вы развернете основной 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.

43 голосов
/ 17 марта 2011

Мое решение в Ubuntu 10.04 с использованием java-sun 1.6.0_24, в котором все jar-файлы находятся в каталоге "lib":

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

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

java -cp $(for i in lib/*.jar ; do echo -n $i: ; done). my.main.Class
33 голосов
/ 15 октября 2012

Для меня это работает в Windows.

java -cp "/lib/*;" sample

Для Linux

java -cp "/lib/*:" sample

Я использую Java 6

32 голосов
/ 21 декабря 2011

Краткий ответ: java -classpath lib/*:. my.package.Program

Oracle предоставляет документацию по использованию подстановочных знаков в classpath здесь для Java 6 и здесь для Java 7 , под заголовком раздела Понимание подстановочных знаков пути к классам . (Когда я пишу это, две страницы содержат одинаковую информацию.) Вот краткое изложение основных моментов:

  • Как правило, для включения всех JAR-файлов в данный каталог вы можете использовать подстановочный знак * (, а не *.jar).

  • Подстановочный знак соответствует только файлам JAR, а не файлам классов; чтобы получить все классы в каталоге, просто закройте запись classpath в имени каталога.

  • Указанные выше два параметра можно объединить, чтобы включить все файлы JAR и классов в каталог, и применяются обычные правила приоритета пути к классам. Например. -cp /classes;/jars/*

  • Подстановочный знак будет не искать JAR-файлы в подкаталогах.

  • Вышеуказанные маркеры верны, если вы используете системное свойство CLASSPATH или флаги командной строки -cp или -classpath. Однако, если вы используете заголовок манифеста Class-Path JAR (как вы могли бы сделать с файлом сборки ant), подстановочные знаки не будут учитываться.

Да, моя первая ссылка такая же, как и в ответе с наибольшим количеством баллов (который я не надеюсь обгонять), но этот ответ не дает большого объяснения помимо ссылки. Так как такого рода поведение не рекомендуется в случае переполнения стека в наши дни , я подумал, что я остановлюсь на этом.

26 голосов
/ 07 марта 2010

Вы можете попробовать Java -Djava.ext.dirs=jarDirectory http://docs.oracle.com/javase/6/docs/technotes/guides/extensions/spec.html

Каталог для внешних jar-файлов при запуске java

21 голосов
/ 13 февраля 2012

Корректное

java -classpath "lib/*:." my.package.Program

Неправильно:

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
21 голосов
/ 18 июля 2016

Windows :

 java -cp file.jar;dir/* my.app.ClassName

Linux :

 java -cp file.jar:dir/* my.app.ClassName

Напомните:
- Windows разделитель пути - ;
- Linux разделитель пути - :
- В Windows, если аргумент cp не содержит пробелов, «кавычки» необязательны

9 голосов
/ 20 октября 2008

Если вам действительно нужно указать все файлы .jar динамически, вы можете использовать сценарии оболочки или Apache Ant . Есть проект общего пользования под названием Commons Launcher , который в основном позволяет вам указать ваш скрипт запуска как файл сборки ant (если вы понимаете, о чем я).

Затем вы можете указать что-то вроде:

<path id="base.class.path">
    <pathelement path="${resources.dir}"/>
    <fileset dir="${extensions.dir}" includes="*.jar" />
    <fileset dir="${lib.dir}" includes="*.jar"/>
</path>

В вашем файле запуска сборки, который запустит ваше приложение с правильным classpath.

...