что такое classpath в java

Pro Java

Страницы

3 апр. 2015 г.

Разбираемся с classpath в Java. Часть 1.

Теперь быстренько разберемся 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

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

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

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

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

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

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

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

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

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

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

jar cf HelloWorld.jar Hello.class Word.class

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

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

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

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

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

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

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

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

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

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

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

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

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

Источник

Что такое classpath и как мне его установить?

Я просто читал эту строку:

Первое, что делает метод format (), это загружает шаблон Velocity из пути к классу с именем output.vm

Пожалуйста, объясните, что подразумевалось под classpath в этом контексте, и как мне установить classpath.

При программировании на Java вы делаете другие классы доступными для написанного вами класса, помещая что-то вроде этого в верхней части исходного файла:

Или иногда вы «массово импортируете» вещи, говоря:

Итак, позже в вашей программе, когда вы говорите:

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

Было бы нецелесообразно, чтобы VM просматривал каждую папку на вашем компьютере, поэтому вы должны предоставить VM список мест для поиска. Это делается путем помещения папок и файлов jar в ваш путь к классам.

Читайте также:  что смотреть на небе сегодня ночью

Итак, классовые пути содержат:

Как вы устанавливаете свой путь к классу?

Первый способ, которым все, кажется, учатся, с переменными среды. На Unix-машине вы можете сказать что-то вроде:

На компьютере с Windows вам нужно перейти к настройкам вашей среды и либо добавить, либо изменить уже существующее значение.

Так каков лучший способ сделать это?

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

Источник

Создание самодостаточных исполняемых JAR

Когда ваше программное приложение выходит за пределы десятка строк кода, вам, вероятно, следует разделить код на несколько классов. На этом этапе встает вопрос о том, как их распределить. В Java классическим форматом является Java-архив, более известный как JAR. Но реальные программы, вероятно, зависят от других JAR.

Что такое самодостаточный JAR?

У MainClass метод static main(String…​ args)

Работа с classpath

Новые проблемы возникают при дистрибуции JAR, которые зависят от других JAR:

Вам необходимо синхронизировать версии библиотек.

3. По этой причине вам необходимо поместить JAR в то же место, относительное или абсолютное, в целевую файловую систему в соответствии с манифестом. Это означает, что сначала нужно открыть JAR и прочитать манифест.

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

Плагин Spring Boot (Для проектов Spring Boot)

Плагин Apache Assembly

Assembly Plugin для Apache Maven позволяет разработчикам объединять результаты проекта в единый распространяемый архив, который также содержит зависимости, модули, документацию сайта и другие файлы.

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

Ссылайтесь на предварительно определенную самодостаточную конфигурацию JAR

Установите главный класс для исполнения

Привяжите к package после формирование исходного JAR

Запуск mvn package дает два артефакта:

Первый JAR имеет то же содержимое, что и тот, который был бы создан без плагина. Второй — это самодостаточный JAR. Вы можете выполнить его следующим образом:

В зависимости от проекта он может выполняться успешно. или нет. Например, в примере проекта Spring Boot он не работает со следующим сообщением:

Зачастую плагин следует стратегии «побеждает последний записавший». Порядок основывается на имени JAR.

С помощью Assembly вы можете нек. Если вам нужно объединить ресурсы, вы, вероятно, захотите использовать плагин Apache Shade.

Плагин Apache Shade

Плагин Assembly является общим; плагин Shade ориентирован исключительно на задачу создания самодостаточных JAR.

Этот плагин предоставляет возможность упаковать артефакт в uber-jar, включая его зависимости, и оттенить — т.е. переименовать — пакеты некоторых зависимостей.

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

Хотя вы можете разработать свой преобразователь, плагин предоставляет набор готовых преобразователей:

Конфигурация плагина Shade к приведенному выше Assembly выглядит следующим образом:

shade привязан к фазе package по умолчанию

Этот преобразователь предназначен для генерации файлов манифеста

Выполните ввод Main-Class

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

Запуск mvn package дает два артефакта:

При работе с проектом, взятым за образец, финальный исполняемый файл все еще не работает так, как ожидалось. Действительно, во время сборки появляется множество предупреждений о дублировании ресурсов. Два из них мешают корректной работе проекта. Чтобы правильно их объединить, нам нужно посмотреть на их формат:

META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat: этот Log4J2 файл содержит предварительно скомпилированные данные плагина Log4J2. Он закодирован в двоичном формате, и ни один из готовых преобразователей не может объединить такие файлы. Тем не менее, случайный поиск показывает, что кто-то уже занимался этой проблемой и выпустил преобразователь для работы с объединением.

META-INF/spring.factories : эти файлы, специфичные для Spring, они имеют формат «один ключ/много значений». Поскольку они текстовые, ни один готовый преобразователь не может корректно объединить их. Однако разработчики Spring предоставляют такую возможность (и многое другое) в своем плагине.

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

Объедините файлы /META-INF/spring.factories

Добавьте необходимый код для преобразователей

Эта конфигурация работает! Тем не менее, есть оставшиеся предупреждения:

Лицензии, предупреждения и схожие файлы

Файлы конфигурации Service Loader

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

Плагин Spring Boot

Плагин Spring Boot использует совершенно другой подход. Он не объединяет ресурсы из JAR по отдельности; он добавляет зависимые JAR по мере их появления в uber JAR. Для загрузки классов и ресурсов он предоставляет специальный механизм. Очевидно, что он предназначен для проектов Spring Boot.

Читайте также:  мкк хорошая история личный кабинет

Настройка плагина Spring Boot проста:

Давайте проверим структуру финального JAR:

Скомпилированные классы проекта

Загрузка классов в Spring Boot

Вот выдержка из манифеста по образцу проекта:

Как вы можете видеть, главный класс является специфичным классом Spring Boot, в то время как «настоящий» главный класс упоминается в другой записи.

Для получения дополнительной информации о структуре JAR, пожалуйста, ознакомьтесь со справочной документацией.

Заключение

В этой статье мы описали 3 различных способа создания самодостаточных исполняемых JAR:

Assembly хорошо подходит для простых проектов

Когда проект становится более сложным и вам нужно работать с дублирующимися файлами, используйте Shade

Наконец, для проектов Spring Boot лучше всего использовать специальный плагин.

Полный исходный код этой статьи можно найти на Github в формате Maven.

Материалы для дополнительного изучения:

Что такое «хороший код» — это во многом спорная тема. Кто-то скажет, что если код работает, значит он достаточно хорош. Кто-то обязательно добавит, что код должен быть легок в понимании и сопровождении. А кто-то добавит, что код еще обязательно должен быть быстрым. Об этом уже много написано и сказано. Что же, давайте еще раз поговорим на эту интересную и холиварную тему. Регистрируйтесь на онлайн-интенсив

Источник

What is a classpath and how do I set it?

I was just reading this line:

The first thing the format() method does is load a Velocity template from the classpath named output.vm

Please explain what was meant by classpath in this context, and how I should set the classpath.

10 Answers 10

When programming in Java, you make other classes available to the class you are writing by putting something like this at the top of your source file:

Or sometimes you ‘bulk import’ stuff by saying:

So later in your program when you say:

The Java Virtual Machine will know where to find your compiled class.

It would be impractical to have the VM look through every folder on your machine, so you have to provide the VM a list of places to look. This is done by putting folder and jar files on your classpath.

So, classpaths contain:

How do you set your classpath?

The first way everyone seems to learn is with environment variables. On a unix machine, you can say something like:

On a Windows machine you have to go to your environment settings and either add or modify the value that is already there.

There is a «gotcha» with all of the above. On most systems (Linux, Mac OS, UNIX, etc) the colon character (‘:’) is the classpath separator. In windowsm the separator is the semicolon (‘;’)

So what’s the best way to do it?

Setting stuff globally via environment variables is bad, generally for the same kinds of reasons that global variables are bad. You change the CLASSPATH environment variable so one program works, and you end up breaking another program.

The classpath is the path where the Java Virtual Machine look for user-defined classes, packages and resources in Java programs.

In this context, the format() method load a template file from this path.

The classpath in this context is exactly what it is in the general context: anywhere the VM knows it can find classes to be loaded, and resources as well (such as output.vm in your case).

The classpath is one of the fundamental concepts in the Java world and it’s often misunderstood or not understood at all by java programmes, especially beginners.

Simply put, the classpath is just a set of paths where the java compiler and the JVM must find needed classes to compile or execute other classes.

And Now, suppose we are under C:\ directory and we want to compile our class, Its easy right, just run:

Now for the hard question, we are in the same folder C:\ and we want to run the compiled class.

Despite of what you might think of to be the answer, the right one is:

And if we want to run the Main.class file, we will execute:

org.example.Main is the name of the class.

«.\Users\HP\Desktop\;.\Users\HP\Downloads\commons-lang3-3.10.jar» are the paths (separated by ; in Windows) to the Main and StringUtils classes.

Источник

2 Setting the Class Path

The class path is the path that the Java Runtime Environment (JRE) searches for classes and other resource files.

This chapter covers the following topics:

Synopsis

Class paths to the JAR, zip or class files. Each class path should end with a file name or directory depending on what you are setting the class path to, as follows:

For a JAR or zip file that contains class files, the class path ends with the name of the zip or JAR file.

For class files in an unnamed package, the class path ends with the directory that contains the class files.

For class files in a named package, the class path ends with the directory that contains the root package, which is the first package in the full package name.

Читайте также:  Что такое реплика в тексте диалоге

Multiple path entries are separated by semicolons with no spaces around the equals sign (=) in Windows and colons in Oracle Solaris.

Class path entries that are neither directories nor archives (.zip or JAR files) nor the asterisk ( * ) wildcard character are ignored.

Description

The class path tells the JDK tools and applications where to find third-party and user-defined classes that are not extensions or part of the Java platform. See The Extension Mechanism at
http://docs.oracle.com/javase/8/docs/technotes/guides/extensions/index.html

The class path needs to find any classes you have compiled with the javac compiler. The default is the current directory to conveniently enable those classes to be found.

The JDK, the JVM and other JDK tools find classes by searching the Java platform (bootstrap) classes, any extension classes, and the class path, in that order. For details about the search strategy, see How Classes Are Found at
http://docs.oracle.com/javase/8/docs/technotes/tools/findingclasses.html

Class libraries for most applications use the extensions mechanism. You only need to set the class path when you want to load a class that is (a) not in the current directory or in any of its subdirectories, and (b) not in a location specified by the extensions mechanism.

Classes can be stored in directories (folders) or in archive files. The Java platform classes are stored in rt.jar. For more details about archives and information about how the class path works, see Class Path and Package Names.

Note: Some earlier releases of the JDK had a /classes entry in the default class path. That directory exists for use by the JDK software and should not be used for application classes. Application classes should be placed in a directory outside of the JDK directory hierarchy. That way, installing a new JDK does not force you to reinstall application classes. For compatibility with earlier releases, applications that use the /classes directory as a class library run in the current release, but there is no guarantee that they will run in future releases.

JDK Commands Class Path Options

For very special cases, both the java and javac commands have options that let you change the path they use to find their own class libraries. Most users will never need to use those options.

CLASSPATH Environment Variable

Set CLASSPATH

The CLASSPATH environment variable is modified with the set command. The format is:

The paths should begin with the letter specifying the drive, for example, C:\. That way, the classes will still be found if you happen to switch to a different drive. If the path entries start with backslash (\) and you are on drive D:, for example, then the classes will be expected on D:, rather than C:.

Clear CLASSPATH

If your CLASSPATH environment variable was set to a value that is not correct, or if your startup file or script is setting an incorrect path, then you can unset CLASSPATH with:

This command unsets CLASSPATH for the current command prompt window only. You should also delete or modify your startup settings to ensure that you have the correct CLASSPATH settings in future sessions.

Change Startup Settings

If the CLASSPATH variable is set at system startup, then the place to look for it depends on your operating system:

Windows 95 and 98: Examine autoexec.bat for the set command.

If the CLASSPATH variable is set at system startup, then the place to look for it depends on the shell you are running:

Class Path Wild Cards

The order in which the JAR files in a directory are enumerated in the expanded class path is not specified and may vary from platform to platform and even from moment to moment on the same machine. A well-constructed application should not depend upon any particular order. If a specific order is required, then the JAR files can be enumerated explicitly in the class path.

Class Path and Package Names

The entire package name is specified in the command. It is not possible, for example, to set the class path so it contains C:\java\MyClasses\ utility and use the command java myapp.Cool. The class would not be found.

You might wonder what defines the package name for a class. The answer is that the package name is part of the class and cannot be modified, except by recompiling the class.

An interesting consequence of the package specification mechanism is that files that are part of the same package can exist in different directories. The package name is the same for each class, but the path to each file might start from a different directory in the class path.

Folders and Archive Files

When classes are stored in an archive file (a zi p or JAR file) the class path entry is the path to and including the zip or JAR file. For example, the command to use a class library that is in a JAR file as follows:

Multiple Specifications

Specification Order

Источник

Академический образовательный портал