Ключи classpath и sourcepath в Java

Ключи classpath и sourcepath в Java фото
Author: Tatyana Milkina

В этой статье мы рассмотрим как использовать для компиляции и запуска Java программ ключи -sourcepath и -classpath.

  1. Компиляция с помощью -sourcepath
  2. Что такое Classpath
  3. Использование ключа -classpath
  4. Ключевые моменты

1. Компиляция с помощью -sourcepath

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

Рассмотрим пример, в котором имеется два класса находящихся в разных пакетах - first.Example1 и second.Example2. Класс  first.Example1 создает экземпляр объекта second.Example2:

package first;

import second.Example2;

public class Example1 {
    public static void main(String[] args) {
        Example2 example2 = new Example2();
        System.out.print("Done!");
    }
}

package second;

public class Example2 {
}

И имеется следующая структура каталогов:

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

Давайте попробуем скомпилировать Example1.java так, как делали это ранее:

cd project1
javac –d classes  src/first/Example1.java 

Результат компиляции:

src\first\Example1.java:9: error: package second does not exist
        second.Example2 example2 = new second.Example2();
          ^
src\first\Example1.java:9: error: package second does not exist
        second.Example2 example2 = new second.Example2();
                                     ^
2 errors

Ошибки произошли из-за того, что хотя javac и знал, где найти Example1.java, но он не знал, где находится Example2.java. Для решения этой проблемы используется ключ sourcepath, указывающий на каталоги, в которых компилятору необходимо искать иерархию исходных файлов. В нашем случае это src. Перепишем строку компиляции:

javac -d classes -sourcepath src src/first/Example1.java

Теперь программа компилируется без ошибок. Следует обратить внимание, что javac также скомпилировал файл Example2.java, на который ссылается скомпилированный файл Example1.java.

Ключ sourcepath может содержать несколько каталогов, отделенных точкой с запятой, хотя обычно в этом нет необходимости. Например, если нужно включить как локальный каталог src, так и каталог C:\projects\anotherproject\src, где хранится исходный код для другого проекта, то используем следующую команду:

javac -d classes -sourcepath src;C:\projects\anotherproject\src 
src/first/Example1.java

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

2. Что такое 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 Фото

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

Рассмотрим использование ключа -cp используя классы first.Example1 и second.Example2, описанные в уроке 'Компиляция с помощью -sourcepath'. Но предположим, что класс 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. 

4. Ключевые моменты

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

  1. Ключ -sourcepath указывает каталоги, в которых компилятор должен искать иерархию исходных файлов.
  2. Ключ -sourcepath может содержать несколько каталогов, разделенных точкой с запятой.
  3. -sourcepath может содержать относительные и абсолютные пути.
  4. Ключ -cp может содержать несколько каталогов, разделенных точкой с запятой, как показано в примере при запуске команды java.
  5. Если указывается подкаталог, это НЕ означает что родительский каталог тоже входит в classpath. Например, для ключа -cp ../projectExample2/classes, каталог ../projectExample2 не будет входить в classpath.
  6. Если используется ключ -cp, то команды javac и java НЕ ищут классы в текущем каталоге по умолчанию. Для указания текущего каталога используется точка. Например:
    cd projectExample1/classes
    java -cp .;../../projectExample2/classes first.Example1​
  7. Если ключ -cp НЕ используется, компилятор вносит текущую рабочую директорию (.) в classpath. 
  8. Ключ -cp может содержать относительные и абсолютные пути.

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

Читайте также:
Комментарии
Fazbart
Aug 15, 2021
Я сделал всё так, как здесь сказано, но добавил в исходные java-файлы, чтобы при выполнении class-файлов выводились сообщения. С second.example2.class всё нормально, его сообщение выводится, а вот при выполнении first.example1.class (который ссылается на второй экземпляр) сообщение не выводится, хотя никаких ошибок нет. Как так?
sysadmin
Aug 18, 2021
Пришлите свой код мне на email - tatyana.milkina@gmail.com. Я посмотрю и отвечу вам.
ig.bel89
May 19, 2022
как запустить программу в данном примере не понимаю
milkina
May 24, 2022
ig.bel89, запускается из командной строки. Попробуйте посмотреть видео.