2009-10-23 14 views
59

Kupiłem trzecią bibliotekę Java, która zawiera plik JAR i dwa pliki DLL. Napisałem własny program Java, który wywołuje plik JAR innej firmy. Teraz moje pytanie brzmi: jak mogę spakować cały mój kod do pojedynczego pliku JAR, który zawiera cały mój kod oraz pliki JAR i DLL innych firm?Jak utworzyć plik JAR zawierający pliki DLL?

Wiem, że taki przypadek to SWT. swt.jar zawiera pliki dll, ale nie wiem jak to zrobić i jak sprawić, aby działał poprawnie.

Odpowiedz

68

Po prostu zapakuj go w dowolnym miejscu w słoiku. Trzeba jednak pamiętać o jednej rzeczy - zanim będzie można użyć bibliotek DLL, które rzeczywiście trzeba wyodrębnić z pliku JAR i zrzucić je na dysku twardym, w przeciwnym razie nie będzie można załadować tych plików. W takim przypadku Zrobiłem projekt JNI dla klienta, w którym będę używał takiego słoika spakowanego podczas wojny. Jednakże - przed uruchomieniem jakichkolwiek natywnych metod otrzymam bibliotekę DLL jako zasób i zapiszę ją na dysk w katalogu tymczasowym. Następnie uruchomiłbym regularny kod inicjalizacyjny, gdzie moja biblioteka DLL jest ustawiona w tej samej lokalizacji, którą właśnie napisałem DLL do

Och, i na wszelki wypadek: nie ma nic szczególnego w pakowaniu dll lub jakimkolwiek innym pliku do słoika. To tak jak pakowanie rzeczy na zamek

Oto niektóre kodu I właśnie wykopał się

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

Słowo ostrożności w tym podejściu - należy oczyścić pliki tymczasowe. Jeśli użyjesz ponownie tej samej ścieżki za każdym razem, zastanów się, co się stanie, jeśli wiele aplikacji użyje JAR (jeden zawiedzie, jeśli drugi już ma blokadę na pliku tymczasowym). Po prostu bądź ostrożny - czasami łatwiej jest wdrożyć JAR i DLL osobno. –

+0

Kod można zmienić, aby zastąpić wcześniej zainstalowany plik. W moim przypadku - była to aplikacja internetowa, która nie będzie często poddawana recyklingowi, ale w rzeczywistości - jeśli po prostu skopiujesz kod "tak jak jest", dostaniesz nową kopię bibliotek DLL za każdym razem, gdy ją wykonasz. – Bostone

+7

Jedna rzecz, o której należy pamiętać: korzystał z bibliotek DLL JNI, które były zależne od innych bibliotek DLL. Zawarłem wszystkie pliki DLL wewnątrz słoika i użyłem powyższego kodu do rozpakowania. Ale otrzymywałem wyjątki java.lang.UnsatisfiedLinkError mówiąc "Nie mogę znaleźć bibliotek zależnych". Problem polega na tym, że musisz wywołać funkcję System.load() w bibliotekach DLL, aby najpierw załadować zależne biblioteki DLL. –

6

Zastosowanie http://www.jdotsoft.com/JarClassLoader.php które można załadować biblioteki DLL i słoiki z innym JAR z nieograniczoną gniazdowania. Na przykład DLL może znajdować się w pliku JAR, który znajduje się w innym katalogu głównym JAR. Wszystkie biblioteki DLL i pliki JAR są ładowane tak, jakby były w ścieżce klasy lub biblioteki.

+23

Uwaga dla innych: Licencja to GPLv3, co znacznie ogranicza możliwości zastosowania. –

+4

Uwaga: ten program ładujący klasy rozpakowuje wszystkie zagnieżdżone słoiki w katalogu tymczasowym. Więc działa jak pierwsza odpowiedź. Natywne biblioteki są rozpakowywane tylko w razie potrzeby. – drzymala

+1

Dostępne komercyjne licencje. – drzymala

Powiązane problemy