Есть ли способ включить все файлы jar в каталог в пути к классам?
Я пытаюсь java -classpath lib/*.jar:. my.package.Program
, и он не может найти файлы классов, которые, безусловно, находятся в этих банках. Нужно ли добавлять каждый файл jar в classpath отдельно?
Используя Java 6 или более позднюю версию, параметр classpath поддерживает подстановочные знаки. Обратите внимание на следующее:
"
)*
, а не *.jar
Windows
java -cp "Test.jar;lib/*" my.package.MainClass
Юникс
java -cp "Test.jar:lib/*" my.package.MainClass
Это похоже на Windows, но использует :
вместо ;
, Если вы не можете использовать подстановочные знаки, bash
допускает следующий синтаксис (где lib
- это каталог, содержащий все файлы архива Java):
java -cp $(echo lib/*.jar | tr ' ' ':')
(Обратите внимание, что использование -jar
несовместимо с параметром -jar
. См. Также: Выполнить файл jar с несколькими библиотеками классов из командной строки)
Понимание подстановочных знаков
Из документа Classpath:
Записи пути класса могут содержать символ подстановочного имени базы данных
*
, который считается эквивалентным заданию списка всех файлов в каталоге с расширением.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
командной строки-classpath
(или-cp
). То есть, во всех этих случаях соблюдаются подстановочные знаки. Тем не менее, групповые маски пути класса не выполняются в заголовкеClass-Path jar-manifest
.
Примечание: из-за известной ошибки в java 8, примеры Windows должны использовать обратную косую черту предшествующих записей с завершающей звездочкой: https://bugs.openjdk.java.net/browse/JDK-8131329
В окнах это работает:
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
Сепараторы являются двоеточиями вместо точек с запятой.
Мы обойдем эту проблему, развернув файл основного myapp.jar
основного, который содержит файл manifest (Manifest.mf
), определяющий путь к классам с другими необходимыми банками, которые затем развертываются рядом с ним. В этом случае вам нужно объявить java -jar myapp.jar
при запуске кода.
Итак, если вы разворачиваете основной jar
в какой-то каталог, а затем помещаете зависимые банки в папку lib
ниже, манифест выглядит так:
Manifest-Version: 1.0
Implementation-Title: myapp
Implementation-Version: 1.0.1
Class-Path: lib/dep1.jar lib/dep2.jar
NB: это не зависит от платформы. Мы можем использовать те же банки для запуска на сервере UNIX или на ПК с ОС Windows.
Мое решение на Ubuntu 10.04 с использованием java-sun 1.6.0_24 со всеми банками в каталоге "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
Короткий ответ: java -classpath lib/*:. my.package.Program
Oracle предоставляет документацию по использованию подстановочных знаков в classpaths здесь для Java 6 и здесь для Java 7, под заголовком раздела Общие сведения о шаблонах пути к классам. (Поскольку я пишу это, две страницы содержат ту же информацию.) Здесь краткое изложение основных моментов:
В общем, чтобы включить все JAR в данный каталог, вы можете использовать подстановочный знак *
( не *.jar
).
Подстановочный знак соответствует только JAR, а не файлам классов; чтобы получить все классы в каталоге, просто закончите запись пути к классу в имени каталога.
Вышеуказанные два параметра можно объединить, чтобы включить все JAR и файлы классов в каталог, и применяются обычные правила приоритета classpath. Например. -cp /classes;/jars/*
Подкаталог будет не искать JAR в подкаталогах.
Вышеуказанные маркерные точки верны, если вы используете системное свойство CLASSPATH
или флаги командной строки -cp
или -classpath
. Однако, если вы используете заголовок манифеста Class-Path
JAR (как вы можете сделать с файлом сборки ant), подстановочные знаки будут не выполняться.
Да, моя первая ссылка такая же, как и в ответе на лучший результат (который я не надеюсь на обгон), но этот ответ не дает много объяснений за пределами ссылки. Поскольку такое поведение обескуражено в Qaru в эти дни, я подумал, что я расширю его.
Для меня это работает в окнах.
java -cp "/lib/*;" sample
Для linux
java -cp "/lib/*:" sample
Я использую Java 6
Вы можете попробовать java -Djava.ext.dirs=jarDirectory
http://docs.oracle.com/javase/6/docs/technotes/guides/extensions/spec.html
Каталог внешних банок при запуске java
-Djava.ext.dirs=
, передайте -Djava.ext.dirs=
BEFORE -jar
Правильно
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
Окно:
java -cp file.jar; dir/* my.app.ClassName
Linux:
java -cp file.jar: dir/* my.app.ClassName
Напомните:
- разделитель путей Windows - ; "
- Linux разделитель путей : "
- В Windows, если аргумент cp не содержит пробел, "кавычки" являются необязательными
Если вы используете Java 6, вы можете использовать подстановочные знаки в пути к классам.
Теперь можно использовать подстановочные знаки в определении пути к классам:
javac -cp libs/* -verbose -encoding UTF-8 src/mypackage/*.java -d build/classes
Если вам действительно нужно указать все .jar файлы динамически, вы можете использовать сценарии оболочки, или Apache Ant. Там есть проект commons Commons Launcher, который в основном позволяет указать ваш запуск script как файл сборки ant (если вы понимаете, что я имею в виду).
Затем вы можете указать что-то вроде:
<path id="base.class.path">
<pathelement path="${resources.dir}"/>
<fileset dir="${extensions.dir}" includes="*.jar" />
<fileset dir="${lib.dir}" includes="*.jar"/>
</path>
В вашем файле сборки запуска, который запустит ваше приложение с правильным пути к классам.
Обратите внимание, что расширение подстановочного символа нарушено для Java 7 в Windows.
Подробнее о https://stackoverflow.com/questions/9195073/broken-wildcard-expansion-for-java7-commandline-on-windows7.
Обходной путь заключается в том, чтобы поставить точку с запятой сразу после шаблона. java -cp "somewhere/*;"
К кому это может относиться,
Я нашел это странное поведение в Windows под оболочкой MSYS/MinGW.
Работает:
$ javac -cp '.;c:\Programs\COMSOL44\plugins\*' Reclaim.java
Не работает:
$ 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
Я совершенно уверен, что подстановочный знак не расширяется оболочкой, потому что, например,
$ echo './*'
./*
(Пробовал и другую программу, а не встроенную echo
, с тем же результатом.)
Я считаю, что он javac
, который пытается его расширить, и ведет себя по-разному, есть ли точка с запятой в аргументе или нет. Во-первых, он может пытаться расширить все аргументы, которые выглядят как пути. И только тогда он будет разбирать их, -cp
принимает только следующий токен. (Обратите внимание, что com.comsol.aco_1.0.0.jar
является вторым JAR в этом каталоге.) Это все предположение.
Это
$ javac -version
javac 1.7.0
Короткая форма: если ваша основная часть находится в банке, вам, вероятно, понадобится дополнительный "-jar pathTo/yourJar/YourJarsName.jar", явно объявленный для ее работы (даже если "YourJarsName.jar" был в пути к классам ) (или, выраженный, чтобы ответить на исходный вопрос, который был задан 5 лет назад: вам не нужно явно обновлять каждую банку, но, похоже, даже с java6 вам нужно обновить свою собственную банку...)
Длинная форма: (Я сделал это явным до такой степени, что, надеюсь, даже нарушители java могут использовать это)
Как и многие другие, я использую eclipse для экспорта jars: (File- > Export → 'Runnable JAR File'). В разделе "Обработка библиотеки" eclipse (Juno) есть три варианта:
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"
Как правило, я бы использовал opt2 (и opt1 был определенно разбит), однако собственный код в одной из банок, которые я использую, я обнаружил перерывы с удобным трюком "jarinjar", который затмевает, когда вы выберете этот параметр. Даже после того, как я понял, мне нужен opt3, а затем, найдя эту запись StackOverflow, мне все же понадобилось некоторое время, чтобы понять, как запустить мою основную внешность затмения, поэтому вот что сработало для меня, поскольку оно полезно для других...
Если вы назвали свою банку: "fooBarTheJarFile.jar" и все установлено для экспорта в каталог: "/theFully/qualifiedPath/toYourChosenDir".
(это означает, что поле "Место для экспорта" будет читать: '/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile.jar')
После того, как вы нажмете на конец, вы увидите, что eclipse помещает все библиотеки в папку с именем 'fooBarTheJarFile_lib' в этом каталоге экспорта, что дает вам что-то вроде:
/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
Затем вы можете запускать из любой точки вашей системы с помощью:
java -classpath "/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile_lib/*" -jar /theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile.jar package.path_to.the_class_with.your_main.TheClassWithYourMain
(для Java Newbies: 'package.path_to.the_class_with.your_main' - объявленный пакетный путь, который вы найдете в верхней части файла TheClassWithYourMain.java, который содержит "main (String [] args) {...} ', который вы хотите запустить извне java)
Ловушка, чтобы заметить: это наличие "fooBarTheJarFile.jar" в списке банок на объявленном пути к классам недостаточно. Вам нужно явно объявить "-jar" и обновить местоположение этой банки.
например. это нарушает:
java -classpath "/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile.jar;/theFully/qualifiedPath/toYourChosenDir/fooBarTheJarFile_lib/*" somepackages.inside.yourJar.leadingToTheMain.TheClassWithYourMain
пересчитывается относительными путями:
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
(с использованием java-версии "1.6.0_27", с помощью 64-разрядной виртуальной машины OpenJDK на ubuntu 12.04)
Все вышеперечисленные решения отлично работают, если вы разрабатываете и запускаете приложение Java вне любой среды IDE, например Eclipse или Netbeans.
Если вы используете Windows 7 и используете Eclipse IDE для разработки на Java, вы можете столкнуться с проблемами при использовании командной строки для запуска файлов классов, встроенных в Eclipse.
например. Исходный код в Eclipse имеет следующую иерархию пакетов: edu.sjsu.myapp.Main.java
У вас есть json.jar как внешняя зависимость для Main.java
При попытке запустить Main.java из Eclipse он будет работать без каких-либо проблем.
Но когда вы пытаетесь запустить это с помощью командной строки после компиляции Main.java в Eclipse, он будет снимать некоторые странные ошибки, говорящие "ClassNotDef Error blah blah".
Я предполагаю, что вы находитесь в рабочем каталоге исходного кода.
Используйте следующий синтаксис для запуска из командной строки:
javac -cp "; json.jar" Main.java
java -cp "; json.jar" edu.sjsu.myapp.Main
[Не пропустите. выше]
Это связано с тем, что вы разместили Main.java внутри пакета edu.sjsu.myapp и java.exe будет искать точный шаблон.
Надеюсь, что это поможет!
Для окон требуются кавычки и; следует использовать в качестве разделителя. например:.
java -cp "target\\*;target\\dependency\\*" my.package.Main
класс из 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
Единственный способ, которым я знаю, как это сделать индивидуально, например:
setenv CLASSPATH /User/username/newfolder/jarfile.jar:jarfile2.jar:jarfile3.jar:.
Надеюсь, что это поможет!
for jar in $(ls $HOME/bin/*.jar); do export CLASSPATH=$jar:$CLASSPATH; done
Дикие карты были введены из Java 6. В записи пути класса может содержаться символ подстановочного имени базы данных *, который считается эквивалентным заданию списка всех файлов в каталоге с расширением .jar или .JAR.
java -cp "lib/*" -jar %MAINJAR%
Если вам нужны только конкретные банки, вам нужно будет добавить их отдельно. Строка classpath не принимает общие подстановочные знаки, такие как Jar *,.jar, hiber и т.д.
Пример
Следующая запись не работает:
java -cp "Halo.jar;lib/*.jar" ni.package.MainClass
Правильная запись:
java -cp "Halo.jar;lib/*" ni.package.MainClass
Подробнее о.... Java Classpath
Rj
Неправильное решение для установки /* на -cp, но я надеюсь, что вы можете использовать следующий script, чтобы немного облегчить ситуацию для динамических классов классов и каталогов 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;
Сценарий для Linux может иметь аналогичный для Windows. Если в качестве входных данных в "libDir2Scan4jars" указан правильный каталог; script проверит все банки и создаст строку класса path и экспортирует ее в переменную env "tmpCLASSPATH".
Установите путь к классу таким образом, чтобы он соответствовал нескольким банкам и текущим файлам классов каталога.
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
Подумайте о файле jar в качестве корня структуры каталогов. Да, вам нужно добавить их все отдельно.
Вам нужно добавить их все отдельно. Кроме того, если вам действительно нужно просто указать каталог, вы можете развязать все в один каталог и добавить его в свой путь к классам. Однако я не рекомендую этот подход, так как вы рискуете причудливыми проблемами в управлении версиями classpath и неуправляемости.