Перейти к содержимому

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 каталог.

Загрузка классов в Java. Теория

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

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

Введение

Любой класс (экземпляр класса java.lang.Class в среде и .class файл в файловой системе), используемый в среде исполнения был так или иначе загружен каким-либо загрузчиком в Java. Для того, чтобы получить загрузчик, которым был загружен класс А, необходимо воспользоваться методом A.class.getClassLoader().

Классы загружаются по мере надобности, за небольшим исключением. Некоторые базовые классы из rt.jar (java.lang.* в частности) загружаются при старте приложения. Классы расширений ($JAVA_HOME/lib/ext), пользовательские и большинство системных классов загружаются по мере их использования.

Виды загрузчиков

Различают 3-и вида загрузчиков в Java. Это — базовый загрузчик (bootstrap), системный загрузчик (System Classloader), загрузчик расширений (Extension Classloader).

Bootstrap — реализован на уровне JVM и не имеет обратной связи со средой исполнения. Данным загрузчиком загружаются классы из директории $JAVA_HOME/lib. Т.е. всеми любимый rt.jar загружается именно базовым загрузчиком. Поэтому, попытка получения загрузчика у классов java.* всегда заканчиватся null’ом. Это объясняется тем, что все базовые классы загружены базовым загрузчиком, доступа к которому из управляемой среды нет.

Управлять загрузкой базовых классов можно с помощью ключа -Xbootclasspath, который позволяет переопределять наборы базовых классов.

System Classloader — системный загрузчик, реализованный уже на уровне JRE. В Sun JRE — это класс sun.misc.Launcher$AppClassLoader. Этим загрузчиком загружаются классы, пути к которым указаны в переменной окружения CLASSPATH.

Управлять загрузкой системных классов можно с помощью ключа -classpath или системной опцией java.class.path.

Extension Classloader — загрузчик расширений. Данный загрузчик загружает классы из директории $JAVA_HOME/lib/ext. В Sun JRE — это класс sun.misc.Launcher$ExtClassLoader.

Управлять загрузкой расширений можно с помощью системной опции java.ext.dirs.

Понятия

Различают текущий загрузчик (Current Classloader) и загрузчик контекста (Context Classloader).

Current Classloader — это загрузчик класса, код которого в данный момент исполняется. Текущий загрузчик используется по умолчанию для загрузки классов в процессе исполнения. В часности, при использовании метода Class.forName(«»)/ClassLoader.loadClass(«») или при любой декларации класса, ранее не загруженного.

Context Classloader — загрузчик контекста текущего потока. Получить и установить данный загрузчик можно с помощью методов Thread.getContextClassLoader()/Thread.setContextClassLoader(). Загрузчик контекста устанавливается автоматически для каждого нового потока. При этом, используется загрузчик родительского потока.

Модель делегирования загрузки

Начиная с версии Java 2 Platform, Standard Edition, v1.2 загрузчики классов образуют иерархию. Корневым является базовый (у него предка нет). Все остальные загрузчики при инициализации инстанциируют ссылку на родительский загрузчик. Такая иерархия необходима для модели делегирования загрузки. В общем случа, иерархия выглядит следующим образом.

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

Рассмотрим процесс загрузки более детально. Пусть в систем исполнения встретилась декларация переменной пользовательского класс Student.

1) Системный загрузчик попытается поискать в кеше класс Student.
_1.1) Если класс найден, загрузка окончена.
_1.2) Если класс не найден, загрузка делегируется загрузчику расширений.
2) Загрузчик расширений попытается поискать в кеше класс Student.
_2.1) Если класс найден, загрузка окончена.
_2.2) Если класс не найден, загрузка делегируется базовому загрузчику.
3) Базовый загрузчик попытается поискать в кеше класс Student.
_3.1) Если класс найден, загрузка окончена.
_3.2) Если класс не найден, базовый загрузчик попытается его загрузить.
__3.2.1) Если загрузка прошла успешно, она закончена 😉
__3.2.2) Иначе управление предается загрузчику раширений.
_3.3) Загрузчик расширений пытается загрузить класс.
__3.3.1) Если загрузка прошла успешно, она закончена 😉
__3.3.2) Иначе управление предается системному загрузчику.
_3.4) Системный загрузчик пытается загрузить класс.
__3.4.1) Если загрузка прошла успешно, она закончена 😉
__3.4.2) Иначе генерируется исключение java.lang.ClassNotFoundException.

Если в системе присутствуют пользовательские загрузчики, они должны
а) расширять класс java.lang.ClassLoader;
б) поддерживать модель динамической загрузки.

Inside

Запустим простейшее приложениие с ключем -verbose:class.

public class A

public class B extends A

public class C extends B

public class Main

public static void main( String args[]) C c = new C();
B b = new B();
A a = new A();
>
>

* This source code was highlighted with Source Code Highlighter .

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

[Loaded Main from file:/C:/devel/CL/bin/]
[Loaded A from file:/C:/devel/CL/bin/]
[Loaded B from file:/C:/devel/CL/bin/]
[Loaded C from file:/C:/devel/CL/bin/]

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

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