Welcome 微信登录

首页 / 软件开发 / JAVA / JNI的替代者:如何使用JNR访问Java外部函数接口(jnr-ffi)

JNI的替代者:如何使用JNR访问Java外部函数接口(jnr-ffi)2014-08-28 cnblogs Alexia1. JNR简单介绍

继上文“JNI的替代者—使用JNA访问Java外部函数接口”,我们知道JNI越来越不受欢迎,JNI是编写Java本地方法以及将Java虚拟机嵌入本地应用程序的标准编程接口。它管理着JVM和非托管的本地环境之间的边界,提供数据编组和对象生命周期管理协议。

根据JEP(JDK增强提案) 191,JNI在下列几个方面最令开发人员痛苦:

需要开发人员编写C代码,这意味着他们需要具备一个完全不同于Java的世界的专业知识。

由于开发人员必须对JVM如何管理内存和代码多少有一些了解,所以典型的C和Java开发人员通常并不具备使用JNI所需的专业知识。

开发人员必须能够为他们想要支持的每个平台构建代码,或者为终端用户提供适当的工具,由他们来完成这项工作。

相比于相同的库绑定到本地应用程序,基于JNI的库性能通常较差。

JNI充当了一个不透明的安全边界。JDK并不知道库中的函数可能会调用什么,或者库中的代码是否会损害JVM的稳定或安全。

因此JNI创建本地函数的方式并不简单,于是产生了像Java Native Access(JNA)和Java Native Runtime(JNR)这样的库。JNA和JNR都是基于JNI创建的,而JEP 191定义的Java Foreign Function Interface(FFI)可能会基于JNR。使用FFI API而不是JNI绑定本地代码和内存将成为开发人员更喜欢的方式。

FFI API将提供下列特性:

一个描述本地库调用和本地内存结构的元数据系统。

发现和加载本地库的机制。

基于元数据将库/函数或内存结构绑定到Java端点的机制。

用于Java数据类型和本地数据类型之间编组和解组的代码。

对Java FFI的需求已经产生了JNA和JNR库。JNA库应用更广泛(具体使用参见“JNI的替代者—使用JNA访问Java外部函数接口”)。JNR库更全面,因为它实现了不同层次的抽象,提供了函数和内存元数据,对库和函数绑定进行了抽象。JNR已经在JRuby项目中大量使用,它可能会成为JEP 191的基础。

上面段落来自JEP 191的描述(由参考文献(1)翻译),由此可见虽然JNA使用广泛,但JNR可能更渐趋势,也许在不久的将来JNR-FFI(jffi)就会内建在JDK中与JNI一样成为Java访问外部函数的标准接口。因此,学习使用JNR是非常有必要的。

JNR-FFI项目也托管自Github,其使用方法与JNA差不多,不过JNR并没有给出相应的jar包,需要我们自己打包使用。

2. JNR项目打包(jnr-ffi.jar)——如何打包Github上的maven项目

首先要明确,Github上托管的项目一般是用maven管理构建的,而不是Eclipse/MyEclipse,因此如果你想通过从Github上直接下载项目源码(Download Zip的方式下载)然后导入或拷贝进Eclipse里打包是行不通的。我一开始也是这么做的,发现项目不完整,缺少一些包,因此打成的jar包也是不能用的。

让我惊讶的,在maven官方库里的jnr-ffi.jar包也是不完整的,下载下来也不能用,还有这个地方的所有jnr包,我都试过了,全部不完整,因此只能自己打包。

在打包之前,你首先需要将完整的源码下载下来,然后有两种方式打包成jar文件。

将maven项目导入Eclipse中打包

通过maven命令mvn打包

两种方法都有需要注意的地方。不熟悉maven的人可以采取第一种方式,上手简单。熟悉maven的当然推荐用mvn命令打包,不过需要注意这里有第三方依赖包,不是一句简单的命令就可搞定。

将maven项目导入Eclipse中打包

注意:虽然Eclipse内置了Maven插件,但表示不太好用,经常出现问题,建议卸载Eclipse的自带的maven插件,然后安装第三方的m2eclipse插件,该插件目前有效的安装地址为:http://download.eclipse.org/technology/m2e/releases,通过Eclipse中Help—Install New Software...—Add Repository安装即可。

有了maven插件后,打包的具体步骤如下:

(1)从Github下载源码

这个其实非常关键,因为不能通过“Download Zip”的方式直接从Github网页上下载,这样下载的源码缺少很多j依赖的ar包,需要通过git clone的方式下载

git clone https://github.com/jnr/jnr-ffi.git

下载后的项目源码就在当前命令行路径下。