Classpath, включаючи JAR в межах JAR


Відповіді:


94

Якщо ви намагаєтеся створити єдину банку, яка містить вашу програму та її необхідні бібліотеки, це є два способи (про які я знаю). Перший - One-Jar , який використовує спеціальний завантажувач класів, щоб дозволити гніздування банок. Другий - UberJar , (або Shade) ), який вибухає включені бібліотеки і ставить усі класи в банку верхнього рівня.

Я також повинен зазначити, що UberJar і Shade є плагінами для Maven1 і Maven2 відповідно. Як було сказано нижче, ви також можете використовувати плагін для складання (який насправді є набагато потужнішим, але набагато складніше правильно налаштувати).


81
Отже, ось ми, через 5 років. Схоже, це все-таки так. Дуже сумно :(
T3rm1

3
Найкращий спосіб, який я зараз знаю, - це використовувати артефакт баночки IntelliJ. Він витягує всі класи з залежних банок і кладе їх у вашу одну банку.
enl8enmentnow

2
Це неможливо в деяких ситуаціях, наприклад, коли ви використовуєте реалізацію JCE на зразок BouncyCastle, яку потрібно підписати
дебюти

1
@ BrainSlugs83 ... Що ти намагаєшся зробити? Я думаю, що завантажувач класів та пакувач One-Jar все ще є відповіддю на включення Jar у проекти Jar (для Java SE). Використання UberJar усуває проблему шляхом вилучення файлів класу у ваш Jar.
Стів Моєр

1
Посилання UberJar потребує облікових даних для входу. Чи є веб-сторінка-наступник?
Томас Веллер

50

Ви НЕ хочете використовувати ці рішення "підірвати вміст JAR". Вони напевно ускладнюють бачити речі (оскільки все вибухає на одному рівні). Крім того, можуть бути конфліктні іменування (не повинно відбуватися, якщо люди використовують належні пакунки, але ви не завжди можете це контролювати).

Потрібна особливість - це один з 25 найкращих радіочастотних радіостанцій Сонця : RFE 4648386 , який Sun у своїй нескінченній мудрості визначив як низький пріоритет. Ми можемо лише сподіватися, що Сонце прокинеться ...

Тим часом, найкращим рішенням, яке я натрапив (на який я б хотів, щоб Sun копіював у JDK), - це використовувати навантажувач спеціального класу JarClassLoader .


4
Конфлікти в іменах насправді майже гарантовано трапляються з такими предметами, як конфігурація log4j та тексти ліцензій.
Майкл Боргвардт

1
На жаль, JarClassLoader - це GPLv3 / комерційний, тому він, ймовірно, не буде "скопійований сонцем (зараз оракул)", і не може бути комерційно використаний, якщо у вас немає внутрішнього політичного рішення та часу, щоб придбати щось. Я згоден, однак, що банки, які перебувають у поточному каталозі, - це погана річ.
Гас

+1 для ідеї у цій відповіді (хоча я не буду ставити +1 до самої відповіді): ви не можете повторно упакувати жоден підписаний файл JAR, тому цю техніку не можна використовувати в багатьох ситуаціях (наприклад, Java activation.jar).
Крістофер Шульц

31

Після деяких досліджень я знайшов метод, який не потребує maven або будь-якого стороннього розширення / програми.

Ви можете використовувати "Class-Path" у файлі маніфесту.

Наприклад:

Створіть файл маніфесту MANIFEST.MF

Manifest-Version: 1.0
Created-By: Bundle
Class-Path: ./custom_lib.jar
Main-Class: YourMainClass

Складіть всі свої заняття та запустіть jar cfm Testing.jar MANIFEST.MF *.class custom_lib.jar

cСтенди для створення архіву fвказує на те, що ви хочете вказати файл vдля багатослівного введення mозначає, що ми передамо власний файл маніфесту

Будьте впевнені, що ви включили lib в банку. Ви повинні мати можливість запускати банку у звичайний спосіб.

на основі: http://www.ibm.com/developerworks/library/j-5things6/

всю іншу необхідну інформацію про шлях до класу ви знайдете тут


19
Ця відповідь не працює. від документа Oracle (пов'язаний з бананом вище): "Заголовок Class-Path вказує на класи або файли JAR у локальній мережі, а не на файли JAR у файлі JAR"
sebnukem

Все, що відомо, чи можна це також використовувати в налаштуваннях Android.
Mostowski Згорнутись

2
Він працює для виконуваного сценарію jar (протестовано), але він може не працювати, коли ви хочете включити банку в jar бібліотеку.
Кічіх

5
О ні, це не працює, як тільки я custom_lib.jarвідійшов, банку більше не можна виконувати :(
Cychih

Як можна вказати кілька банок у Class-Path?
Абхішек Тіварі

22

Використовуйте тег zipgroupfileset (використовує ті самі атрибути, що і тег набору файлів ); він розпакує всі файли в каталозі та додасть ваш новий архівний файл. Більше інформації: http://ant.apache.org/manual/Tasks/zip.html

Це дуже корисний спосіб подолати проблему jar-in-a-jar - я знаю, тому що я переглянув це саме питання StackOverflow, намагаючись зрозуміти, що робити. Якщо ви хочете упакувати банку або папку з баночками в свою вбудовану банку разом з Ant, то забудьте про всі ці речі щодо класного чи сторонніх плагінів, все, що вам потрібно зробити, це це (у Ant):

<jar destfile="your.jar" basedir="java/dir">
  ...
  <zipgroupfileset dir="dir/of/jars" />
</jar>

8

Якщо ви будуєте з мурашкою (я використовую мурашник від затемнення), ви можете просто додати зайві файли jar, сказавши Ant, щоб додати їх ... Не обов'язково найкращий метод, якщо у вас є проект, який підтримується декількома людьми, але він працює проект для однієї людини і простий.

наприклад, моєю ціллю, яка будувала файл .jar, було:

<jar destfile="${plugin.jar}" basedir="${plugin.build.dir}">
    <manifest>
        <attribute name="Author" value="ntg"/>
        ................................
        <attribute name="Plugin-Version" value="${version.entry.commit.revision}"/>
    </manifest>
</jar>

Я лише додав один рядок, щоб зробити це:

<jar ....">
    <zipgroupfileset dir="${external-lib-dir}" includes="*.jar"/>
    <manifest>
        ................................
    </manifest>
</jar>

де

<property name="external-lib-dir" 
          value="C:\...\eclipseWorkspace\Filter\external\...\lib" />

був дір із зовнішніми банками. І це все...


6

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


2

Вам потрібно створити спеціальний завантажувач класів, щоб зробити це, або сторонню бібліотеку, яка це підтримує. Ваша найкраща ставка - витягнути банку з часу виконання та додати їх до classpath (або додати їх уже до classpath).


2

Я використовую Maven для моїх Java-версій, у яких є плагін, який називається модулем збірки Maven .

Це робить те, що ви запитуєте, але, як описано в інших пропозиціях, - по суті, вибух всіх залежних банок і рекомбінація їх в одну банку


Плагін для збирання Maven досить болісно використовувати ... UberJar і Shade - плагіни Maven1 і Maven2 (факт, який я повинен був би згадати вище, і робити це зараз)
Стів Моєр,

2

Якщо у вас IDL-програма eclpise, вам просто потрібно експортувати свій JAR та вибрати "Бібліотеки, необхідні для упаковки, у створені JAR". eclipse автоматично додаватиме необхідні залежні JAR у створений JAR, а також генерується деякий завантажувач спеціального класу затемнення, який автоматично завантажує ці JAR.


1

Я збирався порадити витягнути всі файли на одному рівні, а потім зробити банку з результату, оскільки система пакунків повинна тримати їх акуратно відокремленими. Це був би ручний спосіб, я думаю, інструменти, вказані Стівом, це зроблять чудово.



1

Ну, є дуже простий спосіб, якщо ви використовуєте Eclipse.

Експортуйте проект у вигляді файлу Jar "Runnable" (папку правої кнопки миші в межах Eclipse, виберіть "Експорт ..."). Під час налаштування параметрів експорту обов'язково виберіть "Витягнути необхідні бібліотеки в створений Jar". Майте на увазі, виберіть "Витягнути ...", а не "Пакет необхідних бібліотек ...".

Додатково : у налаштуваннях експорту потрібно вибрати конфігурацію запуску. Отже, ви завжди можете створити порожній main () у якомусь класі та використовувати його для конфігурації запуску.

У будь-якому випадку це не гарантовано, що він працює 100% часу - оскільки ви помітите спливаюче повідомлення, яке повідомляє вам про те, щоб перевірити ліцензії файлів Jar, які ви включаєте, і щось про не копіювання файлів підписів. Однак я цим займаюся роками і ніколи не стикався з проблемою.


0

Витягування в Uber-dir працює для мене, оскільки ми повинні використовувати root: \ java та мати код розетки в пакунках з версією. Тобто ca.tecreations-1.0.0. Підписання нормально, оскільки банки недоторкані від завантаженого місця. Підписи третіх сторін неушкодженими, витяг на c: \ java. Там мій реж. Проекту. запустити з запуску так java -cp c: \ java Launcher


Отже, банки в c: \ java \ jars. Джерело, бінарні файли та ресурси в c: \ java. Виключіть резервні копії, властивості, сховище ключів. Розпакуйте до c: \ java та запустіть інструмент формування класового шляху, тому, можливо, ca.tecreations.system.tools.SystemTool або порівняний java клас. Виконай це.
Тім де Вріс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.