CLASSPATH против java.ext.dirs - PullRequest
       39

CLASSPATH против java.ext.dirs

17 голосов
/ 18 февраля 2011

есть ли причина, по которой следует использовать (возможно, очень длинную) переменную CLASSPATH, чтобы указать, какие jar-файлы должны быть при запуске приложения classpath durign, а затем использовать свойство java 1.5+ -Djava.ext.dirs, которое определяет весь каталог (каталоги) банки для поиска?

Для примера из жизни у меня есть отдельное Java-приложение с папкой lib, содержащей все зависимые файлы jar. Если стартовый скрипт устанавливает все (возможно, 20) банок в переменную CLASSPATH, одну за другой. Поскольку теперь мой архив приложений генерируется Maven, я заранее не вижу, какими будут имена файлов jar (например, я изменяю версию JAR). Конечно, я могу просмотреть каталог lib в скрипте запуска и снова добавить все найденные там jar-файлы в переменную CLASSPATH. Или, возможно, сделайте Maven, чтобы сгенерировать этот скрипт для меня. Но тут возникают вопросы:

1) Было бы нормально и целесообразно заменить все это, просто установив свойство java.ext.dirs, чтобы оно содержало + мой дополнительный lib dir в моем сценарии? Есть ли здесь какие-то предостережения?

Спасибо за ответы:)

Ответы [ 3 ]

33 голосов
/ 18 февраля 2011

java.ext.dirs имеет очень специфическое применение: он используется для указания, откуда механизм расширения загружает классы.Используется для добавления функциональности в JRE или в другие библиотеки (например, JAI).Он не предназначен как механизм загрузки классов общего назначения.

Вместо этого используйте подстановочный знак *.Он был представлен в Java 6, поэтому многие люди до сих пор не знают, что это возможно.

5 голосов
/ 23 августа 2014

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

Одно из отличий состоит в том, что если мы укажем наши библиотеки под флагом -Djava.ext.dirs, они будут загружены загрузчик классов расширения (например, sun.misc.Launcher.ExtClassLoader) вместо системного загрузчика классов (например, sun.misc.Launcher.AppClassLoader).

Предполагается, что в нашей библиотекеу нас есть класс с именем Lib.И наше приложение выполняет этот код:

public class Main {
    public static void main(String args[]) {
        System.out.println(System.getProperty("java.ext.dirs"));
        ClassLoader test_cl = Main.class.getClassLoader();
        ClassLoader lib_cl = Lib.class.getClassLoader();
        System.out.println(test_cl == lib_cl);
        System.out.println(test_cl);
        System.out.println(lib_cl);
    }
}

Вывод на консоль будет:

C:\Program Files\Java\jdk1.6.0\jre\lib\ext;C:\WINDOWS\Sun\Java\lib\ext
true
sun.misc.Launcher$AppClassLoader@107077e
sun.misc.Launcher$AppClassLoader@107077e

, когда приложение запускается с помощью команды java -cp "folder/*;." Main.

Однакокогда приложение запускается с помощью команды java -Djava.ext.dirs=folder Main, вместо этого вывод будет:

folder
false
sun.misc.Launcher$AppClassLoader@107077e
sun.misc.Launcher$ExtClassLoader@7ced01
4 голосов
/ 18 февраля 2011

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

Подумайте о старом адском DLL из Windows 3 дня (если вы помните его), когда развивалась похожая ситуация, когда многие, если не большинство разработчиков программного обеспечения, помещали общие библиотеки в каталог Windows / System, потому что они автоматически выбирались оттуда вместо того, чтобы включать их в свои приложения и загружать их явно.

Вместо этого вам нужно иметь отдельный путь к классу для каждого приложения (поэтому нет пути к классу на уровне системы!), Установить его в сценарии запуска и указывать только те файлы JAR и каталоги классов, которые применимы для этого конкретного приложения. Таким образом, несколько приложений с конфликтующими потребностями в библиотеках могут запускаться бок о бок, не мешая функциональности друг друга.

То же самое верно и в том случае, если вы разработчик, и вам не нужно, чтобы какие-либо внешние библиотеки мешали вашему приложению во время тестирования. И есть еще одна вещь: если вы разрабатываете и используете трюк lib / ext (или путь к классу системного уровня), как вы можете быть уверены, что приложение, которое вы собираетесь отправить, поставляется с правильными библиотеками? Если вы забудете включить его в свой установщик или установочный пакет, вы никогда не заметите, потому что он находится на вашей машине в общей папке. Но клиент, у которого нет такой библиотеки, получит ошибки во время выполнения и вскоре позвонит по телефону, требуя поддержки (и, возможно, возврата денег и предоставив вам плохие отзывы в прессе за доставку неисправного продукта).

...