Simplemente empaquételo en cualquier lugar de la jarra. Sin embargo, hay que tener en cuenta una cosa: antes de poder usar los DLL, necesita extraerlos del JAR y volcarlos en el disco duro; de lo contrario, no podrá cargar estos
Así que, básicamente, Hice el proyecto de JNI para el cliente donde usaré tal envase empaquetado dentro de la guerra. Sin embargo, antes de ejecutar cualquier método nativo, obtendría el archivo DLL como recurso y lo escribiría en el disco en el directorio temporal. Luego ejecutaba el código de inicialización regular donde mi DLL está configurada en la misma ubicación. Acabo de escribir una DLL en
Ah, y por las dudas: no hay nada especial en el empaquetado de dll o cualquier otro archivo en el contenedor. Es como el envasado de cosas en postal
Aquí hay un código que acaba de salir cavé
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 palabra de precaución sobre este enfoque: asegúrese de limpiar los archivos temporales. Si vuelve a utilizar la misma ruta cada vez, considere lo que sucede si varias aplicaciones usan su JAR (una falla si la otra ya tiene un bloqueo en el archivo temporal). Solo tenga cuidado: a veces es más fácil implementar JAR y DLL por separado. –
Se puede cambiar el código para sobrescribir el archivo previamente instalado. En mi caso, esta era una aplicación web que no se reciclaría frecuentemente, pero si copia el código "tal cual" obtendrá una nueva copia de archivos DLL cada vez que lo ejecute. – Bostone
Una cosa a tener en cuenta: I estaba usando DLL JNI que dependían de otras DLL. Incluí todas las DLL dentro de un contenedor y usé el código anterior para descomprimir. Pero estaba obteniendo excepciones java.lang.UnsatisfiedLinkError que dicen "No se pueden encontrar bibliotecas dependientes". El problema es que debe llamar a System.load() en las DLL para que las DLL dependientes se carguen primero. –