Pregunta

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 JAR y DLL de terceros?

Sé que SWT es un caso así. El swt.jar incluye archivos dll, pero no sé cómo hacerlo y cómo hacerlo funcionar correctamente.

¿Fue útil?

Solución

Simplemente empácalo en cualquier lugar del frasco. Sin embargo, hay que tener en cuenta una cosa: antes de que pueda usar los DLL, debe extraerlos del JAR y descargarlos en el disco duro. De lo contrario, no podrá cargarlos.

Básicamente, hice el proyecto JNI para el cliente en el que usaré ese contenedor empaquetado dentro de la guerra. Sin embargo, antes de ejecutar cualquier método nativo obtendría la DLL como recurso y la escribiría en el disco en el directorio temporal. Luego ejecutaría el código de inicialización regular en el que mi DLL está configurada en la misma ubicación en la que acabo de escribir DLL para

Ah, y por si acaso: no hay nada especial en empaquetar dll o cualquier otro archivo en el archivo jar. Es como empaquetar cosas en zip

Aquí hay un código que acabo de desenterrar

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
}

Otros consejos

Utilice http://www.jdotsoft.com/JarClassLoader.php que podría cargar archivos DLL y JARs de otro JAR con anidamiento ilimitado. Por ejemplo, DLL podría estar en JAR, que está en otro JAR raíz. Todas las DLL y JAR se cargan como si estuvieran en una ruta de clase o de biblioteca.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top