Basta impacchettarlo ovunque nel barattolo. Una cosa da tenere a mente però - prima di poter usare le DLL è necessario estrarle dal JAR e scaricarle da qualche parte sul disco rigido altrimenti non sarà possibile caricare queste
Quindi fondamentalmente - Ho fatto un progetto JNI per il cliente in cui userò tale barattolo confezionato all'interno della guerra. Tuttavia, prima di eseguire qualsiasi metodo nativo, otterrei la DLL come risorsa e la scriverò sul disco nella directory temp. Quindi eseguirò il normale codice di inizializzazione dove la mia DLL è impostata nella stessa posizione Ho appena scritto DLL su
Oh, e nel caso in cui: non c'è niente di speciale sulla confezione dll o qualsiasi altro file in jar. E 'proprio come il confezionamento di roba nel zip
Ecco alcuni codice che ho appena scavato fuori
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
}
Una parola di cautela su questo approccio: accertati di aver pulito i file temporanei. Se si riutilizza lo stesso percorso ogni volta, considerare ciò che accade se più applicazioni utilizzano il JAR (una fallirà se l'altra ha già un blocco sul file temporaneo). Basta fare attenzione: a volte è più semplice distribuire separatamente JAR e DLL. –
Il codice può essere modificato per sovrascrivere il file precedentemente installato. Nel mio caso - questa era un'app web che non verrà riciclata frequentemente, ma davvero - se copi il codice "così com'è" riceverai una nuova copia di DLL ogni volta che lo esegui. – Bostone
Una cosa da tenere a mente: I stava usando DLL JNI che dipendevano da altre DLL. Ho incluso tutte le DLL all'interno di un barattolo e ho utilizzato il codice sopra per decomprimere. Ma stavo ottenendo eccezioni java.lang.UnsatisfiedLinkError dicendo "Impossibile trovare librerie dipendenti". Il problema è che è necessario chiamare System.load() sulle DLL in modo tale che le DLL dipendenti vengano caricate per prime. –