Включая все банки в каталог в пути Java classpath - программирование

Включая все банки в каталог в пути Java classpath

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

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

4b9b3361

Ответ 1

Используя 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 ' ' ':')

(Обратите внимание, что использование 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 командной строки -classpath (или -cp). То есть подстановочные знаки соблюдаются во всех этих случаях. Однако подстановочные знаки пути к классу не учитываются в заголовке Class-Path jar-manifest.

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

Ответ 2

В окнах это работает:

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

Мы обойдем эту проблему, развернув файл основного 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.

Ответ 4

Мое решение на 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

Ответ 5

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

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

  • В общем, чтобы включить все файлы JAR в данный каталог, вы можете использовать подстановочный знак * (не *.jar).

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

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

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

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

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

Ответ 6

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

java -cp "/lib/*;" sample

Для linux

java -cp "/lib/*:" sample

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

Ответ 8

Правильно

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

Ответ 9

Windows:

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

Linux:

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

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

Ответ 10

Если вам действительно нужно указать все .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>

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

Ответ 11

Если вы используете Java 6, вы можете использовать подстановочные знаки в пути к классам.

Теперь можно использовать подстановочные знаки в определении пути к классам:

javac -cp libs/* -verbose -encoding UTF-8 src/mypackage/*.java  -d build/classes

Ссылка: http://www.rekk.de/bloggy/2008/add-all-jars-in-a-directory-to-classpath-with-java-se-6-using-wildcards/

Ответ 12

Обратите внимание, что расширение подстановочного символа нарушено для Java 7 в Windows.

Подробнее о fooobar.com/questions/243/....

Обходной путь заключается в том, чтобы поставить точку с запятой сразу после шаблона. java -cp "somewhere/*;"

Ответ 13

К кому это может относиться,

Я нашел это странное поведение в 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

Ответ 14

Для окон требуются кавычки и; следует использовать в качестве разделителя. например:.

java -cp "target\\*;target\\dependency\\*" my.package.Main

Ответ 15

Все вышеперечисленные решения отлично работают, если вы разрабатываете и запускаете приложение 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 будет искать точный шаблон.

Надеюсь, что это поможет!

Ответ 16

Короткая форма: если ваша основная часть находится в банке, вам, вероятно, понадобится дополнительный "-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)

Ответ 17

Единственный способ, которым я знаю, как это сделать индивидуально, например:

setenv CLASSPATH /User/username/newfolder/jarfile.jar:jarfile2.jar:jarfile3.jar:.

Надеюсь, что это поможет!

Ответ 18

класс из 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

Ответ 19

Неправильное решение для установки /* на -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".

Ответ 20

Вам нужно добавить их все отдельно. Кроме того, если вам действительно нужно просто указать каталог, вы можете развязать все в один каталог и добавить его в свой путь к классам. Однако я не рекомендую этот подход, так как вы рискуете причудливыми проблемами в управлении версиями classpath и неуправляемости.

Ответ 21

Подумайте о файле jar в качестве корня структуры каталогов. Да, вам нужно добавить их все отдельно.

Ответ 22

Установите путь к классу таким образом, чтобы он соответствовал нескольким банкам и текущим файлам классов каталога.

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

Ответ 23

Дикие карты были введены из 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

Ответ 24

У меня есть несколько банок в папке. JDK1.8 команда работала для меня в JDK1.8 чтобы включить все JDK1.8 присутствующие в папке. Обратите внимание, что включить в кавычки, если у вас есть пробел в classpath

Windows

Компиляция: javac -classpath "C:\My Jars\sdk\lib\*" c:\programs\MyProgram.java

Запуск: java -classpath "C:\My Jars\sdk\lib\*;c:\programs" MyProgram

Linux

Компиляция: javac -classpath "/home/guestuser/My Jars/sdk/lib/*" MyProgram.java

Запуск: java -classpath "/home/guestuser/My Jars/sdk/lib/*: /home/guestuser/programs" MyProgram

Ответ 25

Я пытаюсь запустить файл Java либо как jar, либо как классы в Ubuntu. Я потерпел неудачу в обоих вариантах. Следующим исключением является его вывод.

Download link: https://upload.cat/f694139f88c663b1

java org.statmetrics.Statmetric

или же

Java -cp/home/elias/statmetrics/statmetrics.jar :. org.statmetrics.Statmetrics

или же

java -classpath "/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

Я нашел ответ:

Моя глупость

Первый шаг: Вы должны установить соответствующую Java: у меня была Java 11, но я установил в качестве Java lib путь 8-й версии! - Вы можете установить версию Java здесь:

  sudo update-alternatives --config java

2-й шаг: затем выполните следующую команду, изменив путь и имена файлов на соответствующие пути и файлы:

  java -classpath "/usr/lib/jvm/java-1.8.0-openjdk-amd64/jre/lib/*" -jar /home/elias/statmetrics/statmetrics.jar org.statmetrics.Statmetrics

Это было успешно выполнено!