java - ¿Cómo hacer un archivo JAR que incluya archivos DLL?
swt packaging (2)
Compré una biblioteca Java de terceros que incluye un archivo JAR y dos archivos DLL. Escribí mi propio programa Java que invoca el archivo JAR de terceros. Ahora mi pregunta es ¿cómo puedo empaquetar todo mi código en un solo archivo JAR que incluya todo mi código y el archivo JAR y DLL de terceros?
Sé que SWT es un caso así. swt.jar
incluye archivos dll, pero no sé cómo hacer esto y cómo hacerlo funcionar correctamente.
Simplemente empaquételo en cualquier lugar del frasco. Sin embargo, hay algo que debes tener en cuenta: antes de poder utilizar los archivos DLL, necesitas extraerlos del archivo JAR y volcarlos en el disco duro; de lo contrario, no podrás cargarlos.
Básicamente, hice el proyecto JNI para el cliente, donde usaré ese paquete 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 un código de inicialización regular donde mi DLL está configurada en la misma ubicación en la que escribí la DLL.
Ah, y por las dudas: no hay nada especial en empacar dll o cualquier otro archivo en el jar. Es como empacar cosas en zip
Aquí hay un código que acabo de descubrir
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
}
Use http://www.jdotsoft.com/JarClassLoader.php que podría cargar archivos DLL y JAR de otro JAR con anidamiento ilimitado. Por ejemplo, DLL podría estar en JAR que está en otro root JAR. Todos los archivos DLL y JAR se cargan como si estuvieran en una ruta de acceso de clase o de biblioteca.