让普通Java Library包含C/C++动态库

如何让Java Library包含C/C++的动态库而且实现正确加载呢?

在OSGi环境下,我们可以在MANIFEST.MF定义不同平台(操作系统,CPU架构)要加裁的动态库,然后OSGi Runtime会正确找到它们,我们主要在start()方法里用System.loadLibrary()就可以正确的加载。

可对于POJO Java Library则没有这些便利。如何做呢?最近看到用到一个库叫sqlite-jdbc,它有比较完整的实现方法。现在做个小归纳。

代码结构

把各个平台下的动态库分文件夹放在源代码文件夹里。这样动态库会和.class一起打包进*.jar里(当然你也可用Maven进行更精确的控制),同时便于我们后面用Class.getResourceAsStream()进行调用。

 

动态库的加载

在Java里使用C/C++动态库,都是为了配合native API,使native能正常使用,首先要使这些库能被正确的加载。但在jar里的动态库是不能被System.loadLibrary()正确加载的。所以基本思路就是把它们Extract到真正的文件系统中

下面是加载流程:

  1. 用户可以通过环境变量自己提供动态库。第一步检查有没有设置Jar所需的so环境变量,如果用就不加载Jar包内的。
  2. 如果没有,根据操作系统(System.getProperty(“os.name”))和CPU架构(System.getProperty(“os.arch”)),找到包里对应的库,准备把库拷贝到temporary folder(System.getProperty(“java.io.tmpdir”))中。
  3. 拷贝之前,检查目标目录中是否已有动态库,用MD5码进行比对。
  4. 如果MD5不相同或库不存在,使用getResourceAsStream的方法把库写到目标目录中。
  5. 对非Window系统,赋予”755″权限。
  6. 最后使用System.load()把该动态库加载到JVM Runtime中。

 

总结

这是一个比较完备的方法。有了这套方法,我们还可以结合AntMaven动态的编译C/C++的源码,再打包。MS可以写个库来做实现整个流程。 😀