2009-10-23 9 views
59

Я купил стороннюю библиотеку Java, которая включает в себя JAR-файл и два DLL-файла. Я написал свою собственную программу Java, которая вызывает сторонний JAR-файл. Теперь мой вопрос: Как я могу упаковать весь свой код в один JAR-файл, который включает весь мой код и сторонние JAR и DLL?Как сделать JAR-файл, содержащий файлы DLL?

Я знаю SWT такой случай. В файле swt.jar содержатся файлы dll, но я не знаю, как это сделать и как заставить его работать правильно.

ответ

68

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

Так что в основном - Я сделал проект JNI для клиента, где я буду использовать такой банку, упакованную в течение войны. Однако - перед запуском каких-либо собственных методов я бы получил DLL в качестве ресурса и записал его на диск в каталог temp. Тогда я бы запускал обычный код инициализации, где моя DLL установлена ​​в то же место, где я только что написал DLL:

О, и на всякий случай: нет ничего особенного в упаковке dll или любом другом файле в банку. Это так же, как упаковка материала в почтовый

Вот код, я просто вырыта

public class Foo { 
private static final String LIB_BIN = "/lib-bin/"; 
private final static Log logger = LogFactory.getLog(ACWrapper.class); 
private final static String ACWRAPPER = "acwrapper"; 
private final static String AAMAPI = "aamapi51"; 
private final static String LIBEAU = "libeay32"; 

static { 
    logger.info("Loading DLL"); 
    try { 
     System.loadLibrary(ACWRAPPER); 
     logger.info("DLL is loaded from memory"); 
    } catch (UnsatisfiedLinkError e) { 
     loadFromJar(); 
    } 
} 

/** 
* When packaged into JAR extracts DLLs, places these into 
*/ 
private static void loadFromJar() { 
    // we need to put both DLLs to temp dir 
    String path = "AC_" + new Date().getTime(); 
    loadLib(path, ACWRAPPER); 
    loadLib(path, AAMAPI); 
    loadLib(path, LIBEAU); 
} 

/** 
* Puts library to temp dir and loads to memory 
*/ 
private static void loadLib(String path, String name) { 
    name = name + ".dll"; 
    try { 
     // have to use a stream 
     InputStream in = ACWrapper.class.getResourceAsStream(LIB_BIN + name); 
     // always write to different location 
     File fileOut = new File(System.getProperty("java.io.tmpdir") + "/" + path + LIB_BIN + name); 
     logger.info("Writing dll to: " + fileOut.getAbsolutePath()); 
     OutputStream out = FileUtils.openOutputStream(fileOut); 
     IOUtils.copy(in, out); 
     in.close(); 
     out.close(); 
     System.load(fileOut.toString()); 
    } catch (Exception e) { 
     throw new ACCoreException("Failed to load required DLL", e); 
    } 
} 
    // blah-blah - more stuff 
} 
+7

Предупреждение об этом подходе - убедитесь, что вы очищаете временные файлы. Если вы повторно используете один и тот же путь каждый раз, подумайте о том, что произойдет, если несколько приложений используют JAR (один будет терпеть неудачу, если у другого уже есть блокировка временного файла). Просто будьте осторожны - иногда проще развернуть JAR и DLL отдельно. –

+0

Код может быть изменен для перезаписывания ранее установленного файла. В моем случае это было веб-приложение, которое не будет часто перерабатываться, но действительно, если вы просто скопируете код «как есть», вы получите новую копию DLL при каждом ее выполнении. – Bostone

+7

Следует иметь в виду: I использует JNI DLL, которые зависят от других DLL. Я включил все библиотеки DLL внутри банки и использовал вышеприведенный код для распаковки. Но я получал исключения java.lang.UnsatisfiedLinkError, говорящие «Не могу найти зависимые библиотеки». Проблема в том, что вы должны вызывать System.load() в DLL, чтобы сначала загружать зависимые DLL. –

6

http://www.jdotsoft.com/JarClassLoader.php Использования которая может загрузить библиотеки DLL и баночки из другого файла JAR с неограниченной вложенностью. Например, DLL может находиться в JAR, который находится в другом корневом JAR. Все библиотеки DLL и JAR загружаются, как и в пути к классам или библиотеке.

+23

Примечание для других: Лицензия GPLv3, что существенно ограничивает применимость. –

+4

Также обратите внимание: этот загрузчик классов распаковывает все вложенные банки во временный каталог. Таким образом, он работает как первый ответ. Собственные библиотеки распаковываются только при необходимости. – drzymala

+1

Доступна коммерческая лицензия. – drzymala

Смежные вопросы