Как лучше всего включать сторонние файлы jar в программу Java?

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

zerobot.jar (my file)
libs/pircbot.jar
libs/mysql-connector-java-5.1.10-bin.jar
libs/c3p0-0.9.1.2.jar

Насколько я знаю, «лучший» способ обработки сторонних библиотек — это поместить их в путь к классам в манифесте моего файла jar, который будет работать кросс-платформенно, не замедлит запуск (что может быть связано с ними) и не сталкивается с юридическими проблемами (которые могут возникнуть при переупаковке).

Проблема для пользователей, которые сами предоставляют сторонние библиотеки (пример использования, обновление их для исправления ошибки). Две библиотеки имеют номер версии в файле, что добавляет хлопот.

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

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

Итак, мой вопрос в том, как я должен это делать?


person ZoFreX    schedule 13.03.2010    source источник
comment
@ZoFrex: зачем использовать новый загрузчик классов? Почему бы просто не использовать загрузчик классов по умолчанию, который всегда является URLClassLoader (AFAIK)? Таким образом, у вас будет только один загрузчик классов. Вот как я это делаю, и я отправляю на сотни машин с OS X и Windows (если это дерьмо попадет в вентилятор, я бы изменил способ, которым я это делаю;)   -  person SyntaxT3rr0r    schedule 13.03.2010
comment
Я действительно использую URLClassLoader. Я создаю новый, чтобы ввести динамический путь к классам, вы не можете изменить путь по умолчанию. Второй загрузчик классов, который я написал ранее, для системы плагинов.   -  person ZoFreX    schedule 13.03.2010


Ответы (4)


Мы предоставляем файлы скриптов вместе с jar. Например. некоторые.bat, некоторые.sh и т. д.

А начиная с Java6 вы можете использовать подстановочные знаки для указания путей к классам.

Вот хорошая статья, объясняющая этот подход: https://blogs.oracle.com/mr/entry/class_path_wildcards_in_mustang

person Enno Shioji    schedule 13.03.2010
comment
@Zwei steinen: он хочет быть кроссплатформенным. Java 6 означает, что вы отрежете себя от огромной части пользовательской базы OS X, у которой есть Mac, на которых никогда официально не будет Java 6 (32-битные Mac с процессором). - person SyntaxT3rr0r; 13.03.2010
comment
Э-э-э, для этого проекта совместимость с OS X на самом деле не так важна, и я все равно компилировал для 1.6. Спасибо за подсказку, мне нужно будет проверить, работают ли мои другие проекты на 1.5! - person ZoFreX; 13.03.2010
comment
Я собираюсь указать путь к классам в манифесте jar и потребовать, чтобы конечные пользователи правильно называли сторонние библиотеки при их обновлении. Тем не менее, я отмечаю это как принятое, поскольку в нем содержится самая интересная информация. - person ZoFreX; 15.03.2010

Если ваша аудитория является технической (а похоже, что да, если они готовы добавить новые файлы jar), то, возможно, вы могли бы предоставить файлы .sh и .bat, которые они могут редактировать, чтобы изменить путь к классам? Это будет более прозрачно для них, чем собственный загрузчик классов.

person Brian Slesinsky    schedule 14.03.2010
comment
Это неплохой подход, но он усложняет ситуацию, когда они обновляют основной jar-файл программы, так как их изменения необходимо будет вносить заново. Я думаю, что в целом требовать от них переименования файлов — лучший подход, но если есть жалобы, я, вероятно, пойду по этому пути. - person ZoFreX; 15.03.2010

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

person sysoutnull    schedule 13.03.2010
comment
Если я правильно понимаю, он просто обрабатывает упаковку для моего дистрибутива, а не для пользователей, обновляющих свои внешние библиотеки? - person ZoFreX; 13.03.2010
comment
@bpfurtado: +1, или используйте izpack... Или сделайте то же самое сами, это не сложно. - person SyntaxT3rr0r; 13.03.2010
comment
fat-jar предназначен только для упаковки и не предоставляет механизма обновления для включенных библиотек. Что касается ваших трудностей с дублированием с помощью пользовательского загрузчика классов, я просто выполняю всю разработку/отладку внутри своей IDE, а после этого я использую толстую банку для развертывания, все тесты, которые осталось выполнить с «упакованным» решением, будут связаны с «ClassNotFoundException's , чего никогда не бывает, так как 'толстая банка' работает очень хорошо. - person sysoutnull; 14.03.2010
comment
Я не тестировал Fat-Jar, но многие методы переупаковки всего в одну банку могут замедлить работу. Также стоит отметить, что подобная переупаковка часто не разрешена лицензиями сторонних библиотек, особенно если само приложение не находится под той же лицензией (в моем случае это не open source). - person ZoFreX; 14.03.2010
comment
Замедлить? Как? Вы имеете в виду что-то вроде времени запуска приложения? Потому что я не вижу, чтобы это замедляло время разработки. Что касается лицензий, у вас будут проблемы независимо от того, какое техническое решение вы используете... Я думал, вам нужно техническое решение. Fat-Jar делает именно то, что вы пытались сделать сами, но он довольно стабилен, я никогда не видел, чтобы он зависал, и я много им пользовался. Вам не нужно «изобретать велосипед», таким образом, вы можете сосредоточиться на уникальных функциях вашего приложения;) - person sysoutnull; 15.03.2010
comment
Я имею в виду время запуска, а не время разработки. Некоторые лицензии разрешают объединение, но не переупаковку. Если они не разрешают объединение, то другие перечисленные здесь подходы позволят конечному пользователю вставить их в себя. Это отличное решение для некоторых ситуаций, но оно не соответствует моим основным критериям (обновление). - person ZoFreX; 15.03.2010

Думаю, я пойду по манифестному маршруту. Объявите путь к классам в манифесте для jar записи и добавьте записи для:

libs/pircbot.jar
libs/mysql-connector-java-5-bin.jar
libs/c3p0.jar

Затем, если пользователи захотят перейти на последние версии библиотек, им придется переименовать их в соответствии с тем, что объявлено в манифесте. Я не думаю, что это слишком большая проблема, и это делает вещи намного проще внутри.

Мне также просто не нравится идея автоматической загрузки всего в ./lib/, что кажется потенциально опасным.

person ZoFreX    schedule 14.03.2010