Что такое classpath в java
Перейти к содержимому

Что такое classpath в java

  • автор:

Classpath

В большинстве случаев команды java и javac должны найти другие классы необходимые для компиляции и выполнения. Самый распространенный случай — это использование классов входящих в Java SE. Или, например, нам нужно скомпилировать и запустить класс, который использует другие классы, не входящие в Java SE.

Команды java и javac используют следующий алгоритм поиска:

  1. Они используют один и тот же список каталогов, в которых ищут необходимые файлы.
  2. Обе команды в процессе поиска просматривают список каталогов в одном и том же порядке.
  3. Как только необходимый класс найден, процесс поиска прекращается. Если список каталогов содержит два или более классов с одним и тем же именем, используется первый найденный.
  4. Первое место используемое в процессе поиска — это каталоги содержащие классы Java SE.
  5. Второе место — каталоги определенные в так называемом Сlasspath.

Classpath может быть задано двумя способами:

  1. Как переменная окружения CLASSPATH. Команды java и javac используют этот способ по умолчанию.
  2. Как ключ -classpath (или -cp) команд java и javac. Этот способ переопределяет список каталогов заданный переменной окружения, но только для конкретного вызова. Данный метод является более предпочтительным.

Способы задания Classpath Фото

2. Использование ключа -classpath

Рассмотрим использование ключа -cp используя классы first.Example1 и second.Example2 , описанные здесь. Но предположим, что класс second.Example2 находится в другом проекте и доступны только его .class файлы. На рисунке изображена схема каталогов для данного примера:

Структура каталогов фото

Следующая команда будет использована для компиляции first.Example1 класса, где ключ -cp указывает на расположение .class файла second.Example2 :

cd projectExample1 javac -d classes -cp ../projectExample2/classes src/first/Example1.java 

Для запуска программы используется команда:

cd projectExample1 java -cp classes;../projectExample2/classes first.Example1

Ключ -cp указывает расположение .class файла second.Example2 (как и при компиляции), а также путь для поиска .class файла first.Example1 — classes.

Несколько важных правил при использовании ключа -cp :

  1. Ключ -cp может содержать несколько каталогов, разделенных точкой с запятой, как показано в примере при запуске команды java .
  2. Если указывается подкаталог, это НЕ означает что родительский каталог тоже входит в classpath. Например, для ключа -cp ../projectExample2/classes , каталог ../projectExample2 не будет входить в classpath.
  3. Если используется ключ -cp , то команды javac и java НЕ ищут классы в текущем каталоге по умолчанию. Для указания текущего каталога используется точка. Например:

cd projectExample1/classes java -cp .;../../projectExample2/classes first.Example1​

Презентацию с видео можно скачать на Patreon .

Что такое classpath?

Classpath – это параметр, который указывает приложениям где искать пользовательские классы. По этому адресу должны быть найдены все классы, для которых не применяются специальные загрузчики. На место поиска стандартных классов JRE этот параметр не влияет.

Кроме непосредственно Java-приложений (команда java ), этот параметр применим и для других утилит JDK, таких как javac , javadoc и другие.

Есть два основных способа установки classpath: в переменной окружения ОС CLASSPATH , и в аргументе командной строки -cp (синоним -classpath ). Второй способ предпочтительнее, потому что позволяет устанавливать разные значения для разных приложений. Значение по умолчанию – текущая директория.

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

Если приложение запускается из jar-файла ( java -jar ), classpath должен быть указан в его манифесте.

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

Путь к классу является путем, что среда выполнения Java ищет классы и другие файлы ресурсов. Путь поиска класса (более обычно известный более коротким именем, «путем к классу») может быть установлен, используя любого -classpath опция, вызывая инструмент JDK (привилегированный метод) или устанавливая CLASSPATH переменная окружения. -classpath опция предпочитается, потому что можно установить ее индивидуально для каждого приложения, не влияя на другие приложения и без других приложений, изменяющих его значение.

C:> sdkTool -classpath classpath1 ; classpath2.

C:> set CLASSPATH= classpath1 ; classpath2.

  • Для.jar или.zip файла, который содержит.class файлы, концы пути к классу с именем.zip или.jar файла.
  • Для.class файлов в неназванном пакете путь к классу заканчивается каталогом, который содержит.class файлы.
  • Для.class файлов в именованном пакете путь к классу заканчивается каталогом, который содержит «корневой» пакет (первый пакет на полное имя пакета).

Записи разнообразного пути разделяются точками с запятой. С set команда, важно опустить пробелы от приблизительно, равняется знаку (=).

Путь к классу по умолчанию является текущим каталогом. Установка CLASSPATH переменная или использование -classpath переопределения параметра командной строки, которые значение по умолчанию, так, если Вы хотите включать текущий каталог в путь поиска, следует включать «.» в новые настройки.

Игнорируются записи пути к классу, которые не являются ни каталогами, ни архивами (.zip или.jar файлы), ни *.

Описание

Путь к классу говорит инструменты JDK и приложения, где найти сторонние и определяемые пользователем классы — то есть, классы, которые не являются расширениями Java или частью платформы Java. Путь к классу должен найти любые классы, которые Вы скомпилировали с javac компилятором — его значение по умолчанию является текущим каталогом, чтобы удобно позволить тем классам быть найденными.

JDK, JVM и другие инструменты JDK находят классы, ища платформу Java (начальная загрузка) классы, любые классы расширения, и путь к классу, в том порядке. (Для получения дополнительной информации на поисковой стратегии, см., Как Классы Находятся.) Библиотеки классов для большинства приложений будут хотеть использовать в своих интересах механизм расширений. Вы только должны установить путь к классу, когда Вы хотите загрузить класс, это (a) не в текущем каталоге или в любом из его подкаталогов, и (b) не в расположении, определенном механизмом расширений.

Если Вы обновляете от более старой версии JDK, Ваши настройки запуска могут включать CLASSPATH настройки, которые больше не необходимы. Следует удалить любые настройки, которые не специализированы, такой как classes.zip . Некоторые сторонние приложения, которые используют виртуальную машину Java, могут изменить Ваш CLASSPATH переменная окружения, чтобы включать libaries они используют. Такие настройки могут остаться.

Можно изменить путь к классу при использовании инструментов JDK — опция пути к классу, когда Вы вызываете JVM или другие инструменты JDK или при использовании CLASSPATH переменная окружения. Используя -classpath опция предпочитается по установке CLASSPATH переменная окружения, потому что можно установить это индивидуально для каждого приложения, не влияя на другие приложения и без других приложений, изменяющих его значение.

Классы могут быть сохранены или в каталогах (папки) или в архивных файлах. Классы платформы Java сохранены в rt.jar . Для получения дополнительной информации на архивах и информации о том, как путь к классу работает, см. Понимание пути к классу и имен пакета около конца этого документа.

Важное Примечание: Некоторые более старые версии JDK sofware включали a < jdk-dir >/classes запись в пути к классу по умолчанию. Тот каталог существует для использования программным обеспечением JDK, и не должен использоваться для классов приложений. Классы приложений должны быть помещены в каталог за пределами каталога JDK hierarcy. Тот путь, устанавливая новый JDK не вынуждает Вас переустановить классы приложений. Для совместимости с более старыми версиями, приложения, которые используют < jdk-dir >/classes каталог как библиотека классов будет работать в текущей версии, но нет никакой гарантии, что они будут работать в будущих версиях.

Используя инструменты JDK — опция пути к классу

У java инструментов JDK, jdb, javac, и javah есть a -classpath опция, которая заменяет путь или соединяет каналом определенный CLASSPATH переменная окружения, в то время как инструмент работает. Это — рекомендуемая опция для того, чтобы изменить настройки пути к классу, потому что у каждого приложения может быть путь к классу, в котором это нуждается, не вмешиваясь ни в какое другое приложение.

У java инструмента времени выполнения есть a -cp опция, также. Эта опция является сокращением для -classpath .

Для совершенно особых случаев у и java и javac есть опции, которые позволяют Вам изменять путь, который они используют, чтобы найти их собственные библиотеки классов. Огромное большинство пользователей не будет, чтобы никогда не должно использовать те опции, как бы то ни было.

Используя переменную окружения ПУТИ К КЛАССУ

Вообще, Вы будете хотеть использовать -classpath параметр командной строки, как объяснено в предыдущем разделе. Этот раздел показывает Вам, как установить CLASSPATH переменная окружения, если Вы хотите сделать это, или четкие настройки, перенесенные от предыдущей установки.

Установка ПУТИ К КЛАССУ

CLASSPATH переменная окружения изменяется с командой набора. Формат:

set CLASSPATH=path1;path2 .

Пути должны начаться с буквы, определяющей диск, например, C:\ . Тем путем классы будут все еще найдены, если Вы, окажется, будете переключаться на различный диск. (Если записи пути запускаются с наклонной черты влево ( \ ) и Вы находитесь на диске D: , например, тогда классы будут ожидаться на D: , а не C: .)

Очистка ПУТИ К КЛАССУ

Если Ваш CLASSPATH переменная окружения была установлена в значение, которое не корректно, или если Ваш файл запуска или сценарий устанавливают неправильный путь, можно сбросить CLASSPATH при использовании:

C:> set CLASSPATH= 

Эта команда сбросы CLASSPATH для текущего окна командной строки только. Следует также удалить или изменить свои настройки запуска, чтобы гарантировать, что Вы имеете право CLASSPATH настройки в будущих сеансах.

Изменение Настроек Запуска

Если CLASSPATH переменная устанавливается при системном запуске, место, чтобы искать это зависит от Вашей операционной системы:

Операционная система Метод
Windows 95 и 98 Исследуйте autoexec.bat на команду набора.
Другой (Windows NT, Windows 2000. ) Переменная окружения CLASSPATH может быть установлена, используя утилиту System в Панели управления.

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

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

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

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

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

Расширение подстановочных знаков делается рано до вызова программы main метод, а не поздно, во время процесса загрузки класса непосредственно. Каждый элемент входного пути к классу, содержащего подстановочный знак, заменяется (возможно пустой) последовательность элементов, сгенерированных, перечисляя файлы 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 явный флягой заголовок.

Понимание пути к классу и имен пакета

Классы Java организуются в пакеты, которые отображаются на каталоги в файловой системе. Но, в отличие от файловой системы, всякий раз, когда Вы определяете имя пакета, Вы определяете целое имя пакета — никогда часть его. Например, имя пакета для java.awt.Button всегда определяется как java.awt .

Например, предположите, что Вы хотите, чтобы Среда выполнения Java сочла класс названным Cool.class в пакете utility.myapp . Если путь к тому каталогу C:\java\MyClasses\utility\myapp , Вы установили бы путь к классу так, чтобы он содержал C:\java\MyClasses .

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

C:> java -classpath C:\java\MyClasses utility.myapp.Cool 

Когда приложение работает, JVM использует настройки пути к классу, чтобы счесть любые другие классы определенными в utility.myapp пакет, которые используются Cool класс.

Отметьте, что все имя пакета определяется в команде. Не возможно, например, установить путь к классу, таким образом, это содержит C:\java\MyClasses\utility и используйте команду java myapp.Cool . Класс не был бы найден.

(Можно задаваться вопросом, что определяет имя пакета для класса. Ответ — то, что имя пакета является частью класса и не может быть изменено, кроме, перекомпилировав класс.)

Отметьте: интересное последствие механизма спецификации пакета — то, что файлы, которые являются частью того же самого пакета, могут фактически существовать в различных каталогах. Имя пакета будет тем же самым для каждого класса, но путь к каждому файлу может запуститься с различного каталога в пути к классу.

Папки и архивные файлы

Когда классы сохранены в каталоге (папка), как c:\java\MyClasses\utility\myapp , тогда точки входа пути к классу к каталогу, который содержит первый элемент имени пакета. (в этом случае, C:\java\MyClasses , так как имя пакета utility.myapp .)

Но когда классы сохранены в архивном файле (.zip или.jar файл), запись пути к классу является путем к и включая.zip или.jar файл. Например, чтобы использовать библиотеку классов, которая находится в.jar файле, команда выглядела бы примерно так:

C:> java -classpath C:\java\MyClasses\myclasses.jar utility.myapp.Cool 

Многократные спецификации

Найти файлы класса в каталоге C:\java\MyClasses так же как классы в C:\java\OtherClasses , Вы установили бы путь к классу в:

C:> java -classpath C:\java\MyClasses;C:\java\OtherClasses .

Отметьте, что два пути разделяются точкой с запятой.

Порядок спецификации

Порядок, в котором Вы определяете многократные записи пути к классу, важен. Интерпретатор Java будет искать классы в каталогах в порядке, они появляются в переменной пути к классу. В примере выше, интерпретатор Java будет сначала искать необходимый класс в каталоге C:\java\MyClasses . Только если это не находит, что класс с именем собственным в том каталоге будет интерпретатор заглядывать C:\java\OtherClasses каталог.

Pro Java

Теперь быстренько разберемся classpath, так как это достаточно важная тема для разработки на Java. Естественно я тут не смогу разобрать все тонкости и хитрости, но постараюсь представить самое необходимое чтобы было понимание этой темы. Для желающих разобраться глубже приведу линки для самостоятельного изучения. Ну и как всегда гугль в помощь.

Чтобы понимать что происходит под капотом у любой Java IDE когда она собирает проект и запускает его надо хоть немного попрактиковаться в использовании компилятора javac, среды исполнения java и понять classpath.

По существу classpath указывает компилятору или виртуальной машине где искать классы необходимые для сборки проекта или же его запуска. Немного об этом мы уже узнали тут. Теперь разберемся с этим получше.

Указать где компилятору или виртуальной машине искать классы можно через ключ –classpath или же системную переменную окружения CLASSPATH. Мы рассмотрим оба этих варианта.

Начнем с простого. Вернемся к нашему проекту Hello World (00004E_HelloWorld), там где мы разделили его на два файла Hello.java и Word.java.

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

И так! Понеслась! Воспользуемся Export для создания jar

CP0001

CP0003

После этого мы получим файл HelloWorld.jar готовый к исполнению на виртуальной машине java. Запустим его из командной строки:

CP0004

Запускать jar файлы надо с ключом –jar как показано на скрине выше. Если этот ключ не использовать то вылетит ошибка:

CP0005

Нам сообщили что не знают где искать главный (main) класс для HelloWorld.jar. Но запустить все же можно и без ключа –jar, но уже воспользовавшись на ключом –classpath , для которого существует сокращенный вариант –cp . Вот как это можно сделать:

CP0006

Почему строчка запуска выглядит именно так? Вспоминаем что именно класс Hello.java содержит у нас метод main.

CP0007

Класс Word.java такого метода не имеет.

CP0008

Как я уже говорил метод main – это точка входа в программу, то есть место от куда начинается ее выполнение и поэтому виртуальной машине java надо знать, от куда надо начинать выполнять программу. Если она не может найти метод main, то она начинает ругаться, как это было показано выше.

И так в нашей строчке

java -cp HelloWorld.jar Hello

мы указали что искать метод main надо в классе Hello (расширение .class опускается) по пути HelloWorld.jar. Jar и zip архивы рассматриваются виртуальной машиной как каталоги, поэтому их надо указывать по полному имени с расширением.

Теперь скомпилируем наши классы Hello.java и Word.java самостоятельно из командной строки без помощи Eclipse, чтобы еще глубже понять как все работает. Для чистоты эксперимента рекомендую удалить все файлы с расширением .class и .jar из каталога bin.

Для начал просто скомпилируем исходники в class файлы без упаковки их в jar, чтобы было понятнее.

Переходим в коневой каталог 00004E_HelloWorld и от туда даем команду компиляции

javac -encoding utf8 -d bin src\Hello.java src\Word.java

CP0009

Поскольку у нас программа состоит из двух классов Hello и Word, то их обоих сразу надо указать компилятору. Кроме того так же надо указать и кодировочку исходников. Так же мы указали папку bin – это то куда будут складываться откомпилированные файлы.

Теперь у нас в каталоге bin два файла Hello.class и Word.class. Перейдем в него чтобы запустить программу.

CP0010

Все работает. Но файлики у нас там лежат россыпью классво .class

Теперь упакуем эти файлики .class в jar архив командой

jar cf HelloWorld.jar Hello.class Word.class

и попробуем запустить HelloWorld.jar

CP0012

И вылетела ошибочка. Почему так? Ведь у нас уже есть jar файл в который упакованы оба класса.

CP0013

Но все равно не работает. Это происходит потому, что внутри jar файла мы не указали какой файл у нас имеет метод main.

Запустить наш jar файл все таки можно указав дополнительно, какой класс содержит метод main.

java -cp HelloWorld.jar Hello

CP0014

Теперь все работает. Но согласитесь так запускать jar файл не удобно, так как всегда надо знать какой класс содержит метод main. Если вы смотрели внимательно, то видимо заметили внутри архива HelloWorld.jar папку META-INF. В ней содержится файл MANIFEST.MF

CP0015

Вот в нем и должна содержаться информация о классе содержащем метод main, но пока в нем ее нет.

CP0016

Исправим эту ошибочку. Удалим файлик HelloWorld.jar и создадим его заново, но уже с добавлением информации о классе содержащим метод main. Сделаем это следующей командой

jar cfe HelloWorld.jar Hello Hello.class Word.class

И запустим файл HelloWorld.jar уже как полагается без танцев с бубном.

CP0017

Как видим все работает нормально. Это произошло потому, что файл MANIFEST.MF уже содержит информацию о классе содержащем метод main.

CP0018

Ну вот теперь мы имеем хоть какое-то представление о том что происходит когда какая-либо IDE создает исполняемый jar файл, а так же получили представление о classpath. В следующей статье мы немного углубим его.

P.S. Так же стоит знать что по умолчанию для виртуальной машины java доступны все классы стандартной библиотеки java, а так же все классы в текущем каталоге от куда запускается главный класс содержащий метод main.

Ну и на последок ссылка где про classpath рассказано достаточно подробно. Правда я не знаю как долго она проживет.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *