2009-10-23 50 views
59

我买了第三方Java库,其中包含一个JAR文件和两个DLL文件。我编写了自己的调用第三方JAR文件的Java程序。现在我的问题是如何将所有代码打包到一个包含我所有代码和第三方JAR和DLL的JAR文件中?如何制作包含DLL文件的JAR文件?

我知道SWT就是这样的情况。 swt.jar包含dll文件,但我不知道如何做到这一点以及如何使其正常工作。

回答

68

只是在罐子的任何位置将其打包。有一件事你必须记住 - 虽然在你使用DLL之前,你需要从JAR中提取这些文件并将它们转储到硬盘上,否则你将无法加载这些文件。所以基本上 - 我为客户做了JNI项目,我将在战争中使用这种jar包。但是 - 在运行任何本地方法之前,我会将DLL作为资源并将其写入临时目录中的光盘。然后,我会跑在我的DLL被设置在同一位置我刚写的DLL

哦,以防万一常规初始化代码:没有什么特别的包装DLL或任何其他文件放入罐子。这就像包装的东西到拉链

下面是一些代码,我只是挖了

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 
} 
+7

谨慎对这种方法的一个词 - 确保你清理临时文件。如果每次重新使用相同的路径,请考虑如果多个应用程序使用您的JAR会发生什么情况(如果另一个应用程序已对临时文件锁定,则会发生什么情况)。只要小心 - 有时分开部署JAR和DLL会更容易。 – 2009-10-24 05:50:57

+0

可以更改代码以覆盖以前安装的文件。在我的情况 - 这是一个网络应用程序,它不会被频繁回收,BU确实是 - 如果你只是将代码复制“原样”你会得到的DLL的新副本每次执行它 – Bostone 2009-10-24 06:03:06

+7

有一点要记住:我正在使用依赖于其他DLL的JNI DLL。我将所有DLL包含在一个jar中,并使用上面的代码解压缩。但是我得到java.lang.UnsatisfiedLinkError异常说“无法找到依赖库”。问题是您必须依次调用DLL上的System.load(),以便首先加载依赖的DLL。 – 2010-05-24 21:27:20

6

使用http://www.jdotsoft.com/JarClassLoader.php其中可以加载DLL和JAR文件从无限嵌套另一个JAR。例如,DLL可能位于另一个根JAR中的JAR中。所有DLL和JAR都像在类路径或库路径中一样加载。

+23

他人注意事项:许可证是GPLv3,这大大限制了适用性。 – 2011-11-03 19:24:21

+4

另请注意:这个类加载器将所有嵌套的jar包解包到一个临时目录中。所以它就像第一个答案。本地库仅在需要时解压缩。 – drzymala 2013-02-14 17:15:30

+1

提供商业许可证。 – drzymala 2013-02-14 17:25:05