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
}
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. –
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
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. –