我购买了一个第三方Java库,其中包括一个JAR文件和两个DLL文件。我编写了自己的Java程序来调用第三方JAR文件。现在我的问题是如何将所有代码打包到单个JAR文件中,其中包括所有我的代码以及第三方JAR和DLL文件?
我知道SWT就是这种情况。 swt.jar
包含dll文件,但我不知道如何做这件事以及如何使其正常工作。
只需要将DLL文件放入jar包中的任何位置。但是,请记住,在使用DLL之前,您需要实际从JAR中提取这些文件并将它们转储到硬盘上的某个位置,否则您将无法加载这些文件。
所以基本上,我为客户做了一个JNI项目,其中我将在war中使用这样的jar包。但是,在运行任何本地方法之前,我会将DLL作为资源获取并将其写入临时目录中的磁盘。然后我会运行常规初始化代码,我的DLL设置为我刚刚写DLL的相同位置
哦,以防万一:将DLL或任何其他文件打包到jar中没有什么特别的。它就像将东西打包到zip中一样简单
下面是我找到的一些代码
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
}
使用http://www.jdotsoft.com/JarClassLoader.php,可以从另一个JAR文件中无限嵌套地加载DLL和JAR文件。例如,DLL文件可以在另一个根JAR文件中的JAR文件中。所有的DLL和JAR文件都像它们在类路径或库路径中一样被加载。
getResourceAsStream
在哪里查找资源。 - Joanis