Как указать путь к jar файлу

Обновлено: 02.07.2024

Путь к классам - это параметр в виртуальной машине Java или компиляторе Java, который указывает расположение определяемых пользователем классов и пакетов . Параметр может быть установлен либо в командной строке , либо через переменную среды .

СОДЕРЖАНИЕ

Обзор и архитектура

Подобно классической динамической загрузки поведения, при выполнении Java - программ на Java Virtual Machine находит и загружает классы лениво (он загружает байт - код класса только тогда , когда класс впервые используется). Путь к классам сообщает Java, где искать в файловой системе файлы, определяющие эти классы.

Виртуальная машина ищет и загружает классы в следующем порядке:

  1. классы начальной загрузки: классы, которые являются фундаментальными для платформы Java (включая общедоступные классы библиотеки классов Java и частные классы, которые необходимы для работы этой библиотеки).
  2. классы расширения: пакеты, которые находятся в каталоге расширенийJRE или JDK , jre/lib/ext/
  3. пользовательские пакеты и библиотеки

По умолчанию доступны только пакеты стандартного API JDK и пакеты расширений без необходимости указывать, где их искать. Путь для всех пользовательских пакетов и библиотек должен быть установлен в командной строке (или в манифесте, связанном с файлом Jar, содержащим классы).

Установка пути для выполнения программ Java

Поставка в качестве аргумента приложения

Предположим, у нас есть пакет org.mypackage, содержащий классы:

  • HelloWorld (основной класс)
  • SupportClass
  • UtilClass

а файлы, определяющие этот пакет, физически хранятся в каталоге D: \ myprogram (в Windows ) или / home / user / myprogram (в Linux ).

Файловая структура выглядит так:

Когда мы вызываем Java, мы указываем имя запускаемого приложения: org.mypackage.HelloWorld. Однако мы также должны указать Java, где искать файлы и каталоги, определяющие наш пакет. Итак, чтобы запустить программу, мы используем следующую команду:

  • java это средство запуска среды выполнения Java , тип инструмента SDK (инструмент командной строки, такой как javac , javadoc или apt )
  • -classpath D: \ myprogram устанавливает путь к пакетам, используемым в программе (в Linux, -cp / home / user / myprogram ) и
  • org.mypackage.HelloWorld - это имя основного класса

Установка пути через переменную окружения

Переменная среды с именем CLASSPATH может быть в качестве альтернативы используется для установки пути к классам. В приведенном выше примере мы также можем использовать в Windows:

Правило состоит в том -classpath , что этот параметр, когда он используется для запуска приложения Java, переопределяет CLASSPATH переменную среды. Если ничего не указано, текущий рабочий каталог используется как путь к классам. Это означает, что когда наш рабочий каталог D:\myprogram\ (в Linux /home/user/myprogram/ ), нам не нужно явно указывать путь к классам. Однако при переопределении рекомендуется включить текущую папку "." в путь к классам в случае, если требуется загрузка классов из текущей папки.

То же самое относится не только к модулю запуска java, но и к компилятору javac .

Установка пути к файлу Jar

Если программа использует вспомогательную библиотеку, заключенную в файл Jar под названием supportLib.jar , физически расположенную в каталоге D: \ myprogram \ lib \, и соответствующая физическая файловая структура имеет следующий вид:

необходим следующий параметр командной строки :

Добавление всех файлов JAR в каталог

В Java 6 и выше можно добавить все jar-файлы в определенном каталоге в путь к классам, используя подстановочную нотацию.

Это работает как для -classpath опций, так и для путей к классам среды.

Установка пути в файле манифеста

Если программа была заключена в файл Jar с именем helloWorld.jar , расположенный непосредственно в каталоге D: \ myprogram , структура каталогов будет следующей:

Файл манифеста определен в helloWorld.jar имеет следующее определение:

Файл манифеста должен заканчиваться либо новой строки или возврата каретки.

Программа запускается следующей командой:

Это автоматически запускает org.mypackage.HelloWorld, указанный в классе Main-Class с аргументами. Пользователь не может заменить это имя класса с помощью вызова java -jar . Class-Path описывает расположение supportLib.jar относительно расположения библиотеки helloWorld.jar . Ни абсолютный путь к файлу, который разрешен -classpath параметром в командной строке, ни внутренние пути jar не поддерживаются. Это означает, что если файл основного класса содержится в банке, org / mypackage / HelloWorld.class должен быть допустимым путем в корне в банке.

Несколько записей пути к классам разделяются пробелами:

Примечания к ОС

Синтаксис пути к классам командной строки, тесно связанный с файловой системой, зависит от операционной системы. Например:

  • во всех Unix-подобных операционных системах (таких как Linux и Mac OS X ) структура каталогов имеет синтаксис Unix с отдельными путями к файлам, разделенными двоеточием (":").
  • в Windows структура каталогов имеет синтаксис Windows, и каждый путь к файлу должен быть разделен точкой с запятой («;»).

Это не применяется, если путь к классам определен в файлах манифеста , где каждый путь к файлу должен быть разделен пробелом (""), независимо от операционной системы.

Мой код работает внутри файла JAR, скажем, foo.jar , и мне нужно знать, в коде, в какой папке находится запущенный файл foo.jar .

Так что, если foo.jar находится в C:\FOO\ , я хочу получить этот путь независимо от того, каков мой текущий рабочий каталог.

Посмотрите ответ Fab для решения, которое работает, когда пути включают пробелы. Также обратите внимание, что некоторые ответы ниже касаются вопроса в заголовке (путь к jar), некоторые - к самому вопросу (путь к папке, содержащей jar), а некоторые предоставляют пути к классам внутри файла jar. Осторожно при использовании в ANT! ============== Я называю String path = SomeClass.class.getProtectionDomain (). GetCodeSource (). GetLocation (). GetPath (); и получить: /C:/apache-ant-1.7.1/lib/ant.jar Не очень полезно! Интересно. Оригинальный код, в котором я это использовал, никогда не запускался в ant, поэтому для меня это не проблема. @Dino Fancellu, я испытал именно то, что вы описали. Работает во время разработки, не работает при сборке.

Замените «MyClass» на имя вашего класса.

Очевидно, это будет делать странные вещи, если ваш класс был загружен из не файлового местоположения.

Этот toURI() шаг жизненно необходим, чтобы избежать проблем со специальными символами, включая пробелы и плюсы Правильный однострочный: return new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().toURI()); использование URLDecoder не работает для многих специальных символов. Смотрите мой ответ ниже для более подробной информации. Примечание: это возвращает путь, включая имя файла jar Разве это не указывает на файл jar, а не на работающий каталог? Вам нужно будет сделать результат getParentFile () для этой работы. Кроме того, getProtectionDomain имеет значение null, если вы получаете свой класс от трассировки: val strace = Thread.currentThread().getStackTrace; val path = strace(1).getClass.getProtectionDomain Использование этого метода до Java 8; поместив этот метод в класс, который находится во внешнем Jar-файле, загруженном через class-path, тогда будет указан путь внешнего jar-файла вместо действующего Jar-файла.

Лучшее решение для меня:

Это должно решить проблему с пробелами и специальными символами.

Еще одно примечание: при вызове этой функции из Jar, имя jar добавляется в конце для меня, поэтому пришлось выполнить: path.substring (0, path.lastIndexOf ("/") + 1); / не обязательно разделитель пути. Вы должны сделать (новый файл (путь)). GetParentFile (). GetPath () вместо этого. Здесь нет проблем с добавлением имени файла JAR. UTF-преобразование кажется идеальным решением в сочетании с @Iviggiani one's ( URLDecoder.decode(ClassLoader.getSystemClassLoader().getResource(".").getPath(), "UTF-8"); ) в Linux. Тем не менее, я не пробовал на Windows. Спасибо, это позволило мне загружать файлы, внешние по отношению к моему JAR, с помощью FileInputStream как в Linux, так и в Windows. Просто нужно было добавить расшифрованный путь перед именем файла . Осторожно: не рекомендуется использовать URLDecoder для декодирования специальных символов. В частности, символы like + будут ошибочно декодированы в пробелы. Смотрите мой ответ для деталей.

Чтобы получить File для данного Class , есть два шага:

  1. Преобразовать Class в а URL
  2. Преобразовать URL в а File

Важно понимать оба шага, а не объединять их.

Если у вас есть File , вы можете позвонить, getParentFile чтобы получить содержащую папку, если это то, что вам нужно.

Шаг 1: Class в URL

Как обсуждалось в других ответах, есть два основных способа найти URL отношение к Class .

URL url = Bar.class.getProtectionDomain().getCodeSource().getLocation();

URL url = Bar.class.getResource(Bar.class.getSimpleName() + ".class");

У обоих есть плюсы и минусы.

getProtectionDomain Подход дает основание расположение класса (например, содержащий JAR - файл). Однако, возможно, что политика безопасности среды выполнения Java сработает SecurityException при вызове getProtectionDomain() , поэтому, если ваше приложение должно работать в различных средах, лучше всего протестировать во всех них.

getResource Подход дает полный путь URL ресурса класса, из которого вам нужно будет выполнить дополнительные манипуляции со строками. Это может быть file: путь, но он также может быть jar:file: или даже чем-то более неприятным bundleresource://346.fwk2106232034:4/foo/Bar.class при выполнении в рамках OSGi. И наоборот, getProtectionDomain подход правильно дает file: URL, даже из OSGi.

Обратите внимание, что оба getResource("") и getResource(".") потерпели неудачу в моих тестах, когда класс находился в файле JAR; оба вызова вернули ноль. Поэтому я рекомендую вызов №2, показанный выше, так как он кажется более безопасным.

Шаг 2: URL чтобы File

В любом случае, если у вас есть URL , следующим шагом будет преобразование в File . Это его собственная проблема; см. подробности в блоге Kohsuke Kawaguchi об этом , но вкратце вы можете использовать его, new File(url.toURI()) если URL-адрес полностью сформирован.

Наконец, я бы очень не рекомендовал использовать URLDecoder . Некоторые персонажи URL, : и , / в частности, не являются допустимыми URL-кодированных символов. От URLDecoder Javadoc:

Предполагается, что все символы в закодированной строке являются одним из следующих: от "a" до "z", от "A" до "Z", от "0" до "9" и "-", "_", " .", а также "*". Символ "%" разрешен, но интерпретируется как начало специальной экранированной последовательности.

.

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

На практике, URLDecoder как правило, не бросать, IllegalArgumentException как угрожали выше. И если ваш путь к файлу имеет пробелы, закодированные как %20 , этот подход может работать. Однако, если в вашем пути к файлу есть другие не алфавитные символы, например, у + вас будут проблемы с URLDecoder указанием пути к файлу.

мой код работает внутри файла JAR, скажем foo.jar, и мне нужно знать, в коде, в какой папке работает foo.фляги.

Итак, если Foo.фляги в C:FOO , Я хочу получить этот путь независимо от того, что мой текущий рабочий каталог.

замените "MyClass" на имя вашего класса

очевидно, что это будет делать странные вещи, если класс был загружен из файла.

лучшее решение для меня:

Это должно решить проблему с пробелами и специальными символами.

для получения File для данного Class , есть два шага:

  1. преобразование Class до URL
  2. преобразование URL до File

важно понимать оба шага, а не объединять их.

после File можно назвать getParentFile чтобы получить папку, если это необходимо.

Шаг 1: Class to URL

как говорится в другие ответы, есть два основных способа найти URL , относящиеся к Class .

URL url = Bar.class.getProtectionDomain().getCodeSource().getLocation();

URL url = Bar.class.getResource(Bar.class.getSimpleName() + ".class");

у обоих есть плюсы и минусы.

на getProtectionDomain подход дает базовое местоположение класса (например, содержащий файл JAR). Тем не менее, возможно, что политика безопасности среды выполнения Java бросит SecurityException при вызове getProtectionDomain() , так что если ваше приложение должно работать в различных средах лучше всего тестировать во всех из них.

на getResource подход дает полный путь ресурса URL класса, из которого вам нужно будет выполнить дополнительные манипуляции строками. Это может быть file: путь, но это также может быть jar:file: или даже что-то более гадкое, как bundleresource://346.fwk2106232034:4/foo/Bar.class при выполнении в рамках OSGi. И наоборот, getProtectionDomain подход правильно дает file: URL даже из OSGi.

Шаг 2: URL до File

наконец, я хотел отговаривают используя URLDecoder . Некоторые символы URL, : и / в частности, не являются допустимыми символами в кодировке URL. От URLDecoder Javadoc:

предполагается, что все символы в закодированной строке являются одним из следующих: "a" через "z"," A "через" Z"," 0 "через" 9", и "-", "_", ".", и."*" Символ " % " разрешен, но является интерпретируется как начало специальной escape-последовательности.

.

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

на практике URLDecoder вообще не бросать IllegalArgumentException как угрожали выше. И если путь к файлу содержит пробелы кодируются как %20 этот подход может работать. Однако, если ваш путь к файлу имеет другие не буквенные символы, такие как + у вас будут проблемы с URLDecoder искажение пути к файлу.

Я пытаюсь получить путь к ресурсу, но мне не повезло.

это работает (как в IDE, так и с JAR), но таким образом я не могу получить путь к файлу, только содержимое файла:

Если я сделаю это:

результат: java.io.FileNotFoundException: file:/path/to/jarfile/bot.jar!/config/netclient.p (No such file or directory)

есть ли способ получить путь к файлу ресурса?

это умышленное. Содержимое "файла" может быть недоступно в виде файла. Помните, вы имеете дело с классами и ресурсами, которые могут быть частью файла jar или другого вида ресурса. Загрузчик классов не должен предоставлять дескриптор файла для ресурса, например файл jar не может быть развернут в отдельные файлы в файловой системе.

все, что вы можете сделать, получив java.io. File может быть сделано путем копирования потока во временный файл и делать то же самое, если java.io.файл абсолютно необходим.

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

и

Я думаю, эта путаница вызывает большинство проблем при загрузке ресурса.

кроме того, когда вы загружаете изображение, его проще использовать getResourceAsStream() :

когда вам действительно нужно загрузить файл (без изображения) из архива JAR, вы можете попробовать это:

ответ на одну строку -

в принципе getResource метод дает URL. Из этого URL-адреса вы можете извлечь путь, вызвав toExternalForm()

ссылки:

getResource (), toExternalForm()

Я провел некоторое время возиться с этой проблемой, потому что ни одно решение я не нашел на самом деле работал, как ни странно! Рабочий каталог часто не является каталогом JAR, особенно если JAR (или любая программа, если на то пошло) запускается из меню Пуск под Windows. Так вот что я сделал, и это работает .класс файлы, которые запускаются из-за пределов флягу так же хорошо, как он работает за банку. (Я только протестировал его под Windows 7.)

Если netclient.p находится внутри файла JAR, у него не будет пути, потому что этот файл находится внутри другого файла. в этом случае лучший путь, который вы можете иметь, действительно file:/path/to/jarfile/bot.jar!/config/netclient.p .

вам нужно понять путь в файле jar.
Просто обратитесь к нему относительно. Так что если у вас есть файл (файл myfile.txt), расположенный в foo.баночка под \src\main\resources каталог (стиль maven). Вы бы назвали его так:

Если вы сбрасываете свою банку с помощью jar -tvf myjar.jar вы увидите вывод и относительный путь в файле jar, а также использовать прямые косые черты.

файл-это абстракция для файла в файловой системе, и файловые системы ничего не знают о том, что такое содержимое JAR.

попробуйте с URI, я думаю, что есть jar:// протокол, который может быть полезен для ваших целей.

Это тот же код от пользователя Tombart с потоком flush и close, чтобы избежать неполной временной копии содержимого файла из ресурса jar и иметь уникальные имена временных файлов.

в моем случае, я использовал объект URL вместо пути.

File

ресурс в classpath с помощью classloader

когда мне нужно прочитать содержимое, я могу использовать следующий код:

и вы можете получить доступ к содержимому с помощью InputStream.

следующий путь работал для меня: classpath:/path/to/resource/in/jar

это getSystemResourceAsStream это лучший вариант. Получая inputstream, а не файл или URL-адрес, работает в файле JAR и как автономный.

когда в файле jar ресурс находится абсолютно в иерархии пакетов (а не в иерархии файловой системы). Так что если у вас есть класс com.образец.Сладкая загрузка ресурса с именем"./неисполнение.conf "тогда имя ресурса указывается как" /com/example / default.конф".

но если это в банке, то это не файл .

В папке ressources (java / main / resources) вашего jar добавьте свой файл (мы предполагаем, что вы добавили xml-файл с именем импорт.xml), после чего вы вводите ResourceLoader Если вы используете весна, как ниже

внутри функции тура напишите ниже код для загрузки файла:

Читайте также: