让普通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可以写个库来做实现整个流程。 😀

 

About “Plug-in from Existing JAR Archives” kind projects in maven+tycho build

In Eclipse RCP project, you may need to create such kind of “Plug-in from Existing JAR Archives” projects, because you need to reuse non-OSGi jar, such as Google Guava, SLF4j and etc.

In our team, before we have to manually download the needed jar libs from website, then change build.properties, MANIFEST.MF. And of couse, these libraries should be uploaded to version control system (such as P4, Git), as others (as well as Jenkins) can sync to latest and build.

This approach has some defects:

  • Too much manual work and hard to maintain the dependencis.
  • 3rd party libs become more and more.

Here is a solution for that – using maven dependency:copy-dependencies to copy all needed libs.

tycho + maven

Tycho is a great maven plugin, which can help to do headless build for a Eclipse RCP project. It will analyze the dependencies in MANIFEST.MF and also in pom.xml. We can use the feature to define the 3rd party dependencies in pom.xml.

You can find more usefule information about tycho on Eclipse.com.

Define the needed libraries in pom.xml

Just as what a common maven project does, you can define the libraries you need in <dependencies> of pom.xml, such as,

Use maven-dependency-plugin:copy-dependencies to copy

Use the goal of maven-dependency-plugin:copy-dependencies to copy those jars to specific folder, such as,

The goal is defined at “initialize” phase.

Change MANIFEST.MF

With this pom.xml, you can do a manually build and retrieve the jars from maven repository. Then you need to put them into the bundle’s CLASSPATH and exported packages in MANIFEST.MF.

Summary

Using this way, you don’t need to worry about third party libraries in OSGi environment any more. All dependencies are defined in pom.xml. It’s very clean and clear. Of course, in real world, you need do more configuration in pom.xml (such as clean work) and an IDE environment integration.

 

 

使用Web技术开发桌面客户端的一些准备

有了用Web技术开发客户端的想法,自然就有个疑问,Embedded的Browser到底能力怎么样?

于是便和各桌面流行浏览器的对比实验,Embedded Browser选用的是JavaFX的WebBrowser,也是个基于Webkit的Browser.

不是专业人士,不知道这些测试页有没有代表性。下面是对比结果,

[easy_table caption=”Result Comparison”]Test Page,Firefox 25, Safari 17, Chrome 30, JavaFX, Safari (iOS 7.0.3)
http://browsermark.rightware.com,4051,5163,3701,3323,2627,
http://html5test.com,424,385,463,310,415,
http://css3test.com,58%,61%,60%,51%,61%,
[/easy_table]

显然JavaFX的WebBrowser在各方面都基本是最差的。(Performance比iPhone上的Safari略好,但iPhone毕竟是移动设备,且这个分数比91%的手机都要好。)这结果对于目前的使用场景应该足够了,不会使用很多HTML5和CSS3的高级用法,也不会加载很大的页面,Performance应该不是问题。

接下来做个更贴近产品的Demo吧!