`

jna

    博客分类:
  • java
 
阅读更多

                                                               

            JNA—JNI终结者

转:http://blog.csdn.net/shendl/article/details/3589676

介绍

给大家介绍一个最新的访问本机代码的Java框架—JNA

JNA(Java Native Access)框架是一个开源的Java框架,是SUN公司主导开发的,建立在经典的JNI的基础之上的一个框架。

JNA项目地址:https://jna.dev.java.net/

非常强大、易用,功能上类似与.NETP/Invoke.

不堪回首的JNI

我们知道,使用JNI调用.dll/.so共享类库是非常非常麻烦和痛苦的。

如果有一个现有的.dll/.so文件,如果使用JNI技术调用,我们首先需要另外使用C语言写一个.dll/.so共享库,使用SUN规定的数据结构替代C语言的数据结构,调用已有的  dll/so中公布的函数。

然后再在Java中载入这个适配器dll/so,再编写Java   native函数作为dll中函数的代理。

经过2个繁琐的步骤才能在Java中调用本地代码。

因此,很少有Java程序员愿意编写调用dll/.so库中的原生函数的java程序。这也使Java语言在客户端上乏善可陈。可以说JNIJava的一大弱点!

.NET平台上强大的P/Invoke

而在.NET平台上,强大的P/Invoke技术使我们Java程序员非常羡慕。使用P/Invoke技术,只需要使用编写一个.NET函数,再加上一个声明的标注,就可以直接调用dll中的函数。

不需要你再使用C语言编写dll来适配。

不逊于P/InvokeJNA

现在,不需要再羡慕.NETP/Invoke机制了。JNA把对dll/.so共享库的调用减少到了和P/Invoke相同的程度。

使用JNA,不需要再编写适配用的.dll/.so,只需要在Java中编写一个接口和一些代码,作为.dll/.so的代理,就可以在Java程序中调用dll/so

JNA快速启动

  现在让我们直接进入JNA的世界。

你只需要下载一个jar包,就可以使用JNA的强大功能方便地调用动态链接库中的C函数。

1,下载jna.jar

在这里https://jna.dev.java.net/servlets/ProjectDocumentList?folderID=7408&expandFolder=7408&folderID=0

2,现在你已经可以使用JNA了。

为了方便你参考JNAjava类库,我制作了《JNA3.09API参考手册》,是CHM格式的。你可以到这里下载 http://download.csdn.net/source/900438

JNA例子

例子1   

现在让我们运行一个JNA程序,感受它的强大威力。

1,在Java项目中引入jna.jar包。

2,创建一个类:

 

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;

/**
 * @version: 1
 * @Email:handawei_1@126.com
 * @date: 2011-11-29下午4:42:50
 * @comment: 
 */
public class TestOne {
	/**
	 * @version: 1
	 * @Email:handawei_1@126.com
	 * @date: 2011-11-29下午4:42:50
	 * @param args
	 * @comment: 
	 */
	public static void main(String[] args){
		CLibrary.INSTANCE.printf("Hello,World\n");
		for(int i=0;i<args.length;i++)
		{
			CLibrary.INSTANCE.printf("Argument%d:%s\n", i,args[i]);
		}
	}
	interface CLibrary extends Library
	{
	  CLibrary INSTANCE=(CLibrary)Native.loadLibrary(Platform.isWindows()?"msvcrt":"c", CLibrary.class);
	  void printf(String format,Object...args);
	}
}

 

3,执行,可以看到控制台中打印出了

Hello, World

    但是,请注意,这个程序实际上是使用msvcrt.dll这个C运行时库中的printf函数打印出上面这些字符的。

    看,多简单,不需要写一行C代码,就可以直接在Java中调用外部动态链接库中的函数!

例子2   

    上面那个例子使用了操作系统自带的动态链接库,现在我们再自己写一个动态链接库试试。

1,在VS中选择C++语言,然后选择创建一个Win32程序。选择dll类型。

2,发布的C函数是:

#define MYLIBAPI  extern   "C"     __declspec( dllexport )  
 
MYLIBAPI void say(wchar_t* pValue);

 

这个函数的实现是:

 

 

 

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.WString;
 
/**
 * @author 沈东良 Edward Shen shendl_s@hotmail.com
 * 2008-11-23 下午05:07:14
 *TestDll1.dll
 */
public class TestDll1Service {
 
         public interface TestDll1 extends Library { 
                   /**
                    * 当前路径是在项目下,而不是bin输出目录下。
                    */
                   TestDll1 INSTANCE = (TestDll1)Native.loadLibrary("TestDll1", TestDll1.class);
                   public void say(WString value);
                   
         }
         /**
          * 
          */
         public TestDll1Service() {
                   // TODO Auto-generated constructor stub
         }
 
         /**
          * @param args
          */
         public static void main(String[] args) {
                   // TODO Auto-generated method stub
                   
                   TestDll1.INSTANCE.say(new WString("Hello World!"));
                   System.out.println("HHEEH我我们无法万恶");
         }
 
}

 

5,执行这个Java类。可以看到控制台下如下输出:

上帝说:Hello World!

HHEEH我我们无法万恶

 

6,上面一行是C语言使用C++std::wcout输出的。

下面一行是Java语言输出的。

JNA技术解密

JNA工作原理

JNA是建立在JNI技术基础之上的一个Java类库,它使您可以方便地使用java直接访问动态链接库中的函数。

原来使用JNI,你必须手工用C写一个动态链接库,在C语言中映射Java的数据类型。

JNA中,它提供了一个动态的C语言编写的转发器,可以自动实现JavaC的数据类型映射。你不再需要编写C动态链接库。

当然,这也意味着,使用JNA技术比使用JNI技术调用动态链接库会有些微的性能损失。可能速度会降低几倍。但影响不大。

JNA技术难点

1,当前路径是在项目下,而不是bin输出目录下。

2,数据结构的对应关系:

Java—C和操作系统数据类型的对应

Java Type

C Type

Native Representation

boolean

int

32-bit integer (customizable)

byte

char

8-bit integer

char

wchar_t

platform-dependent

short

short

16-bit integer

int

int

32-bit integer

long

long long, __int64

64-bit integer

float

float

32-bit floating point

double

double

64-bit floating point

Buffer
Pointer

pointer

platform-dependent (32- or 64-bit pointer to memory)

<T>[] (array of primitive type)

pointer
array

32- or 64-bit pointer to memory (argument/return)
contiguous memory (struct member)

除了上面的类型,JNA还支持常见的数据类型的映射。

String

char*

NUL-terminated array (native encoding or jna.encoding)

WString

wchar_t*

NUL-terminated array (unicode)

String[]

char**

NULL-terminated array of C strings

WString[]

wchar_t**

NULL-terminated array of wide C strings

Structure

struct*
struct

pointer to struct (argument or return) (or explicitly)
struct by value (member of struct) (
or explicitly)

Union

union

same as Structure

Structure[]

struct[]

array of structs, contiguous in memory

Callback

<T> (*fp)()

function pointer (Java or native)

NativeMapped

varies

depends on definition

NativeLong

long

platform-dependent (32- or 64-bit integer)

PointerType

pointer

same as Pointer

 

JNA编程过程

JNA把一个dll/.so文件看做是一个Java接口。

DllC函数的集合、容器,这正和接口的概念吻合。

    我们定义这样一个接口,

public interface TestDll1 extends Library {

                   /**

                    * 当前路径是在项目下,而不是bin输出目录下。

                    */

                   TestDll1 INSTANCE = (TestDll1)Native.loadLibrary("TestDll1", TestDll1.class);

                   public void say(WString value);

                  

         }

如果dll是以stdcall方式输出函数,那么就继承StdCallLibrary。否则就继承默认的Library接口。

 

接口内部需要一个公共静态常量:instance

TestDll1 INSTANCE = (TestDll1)Native.loadLibrary("TestDll1", TestDll1.class);

通过这个常量,就可以获得这个接口的实例,从而使用接口的方法。也就是调用外部dll的函数!

注意:

1Native.loadLibrary()函数有2个参数:

    1dll或者.so文件的名字,但不带后缀名。这符合JNI的规范,因为带了后缀名就不可以跨操作系统平台了。

搜索dll的路径是:

1)项目的根路径

2)操作系统的全局路径、

3path指定的路径。

2,第二个参数是本接口的Class类型。

JNA通过这个Class类型,根据指定的dll/.so文件,动态创建接口的实例。

2,接口中你只需要定义你需要的函数或者公共变量,不需要的可以不定义。

public void say(WString value);

参数和返回值的类型,应该和dll中的C函数的类型一致。

这是JNA,甚至所有跨平台调用的难点。

这里,C语言的函数参数是:wchar_t*

JNA中对应的Java类型是WStirng

所有跨平台、跨语言调用的难点

有过跨语言、跨平台开发的程序员都知道,跨平台、语言调用的难点,就是不同语言之间数据类型不一致造成的问题。绝大部分跨平台调用的失败,都是这个问题造成的。

关于这一点,不论何种语言,何种技术方案,都无法解决这个问题。

这需要程序员的仔细开发和设计。这是程序员的责任。

常见的跨平台调用有:

1Java调用C语言编写的dll.so动态链接库中的函数。

2.NET通过P/Invoke调用C语言编写的dll.so动态链接库中的函数。

3,通过WEBService,在C,C++,Java,.NET等种种语言间调用。

    WebService传递的是xml格式的数据。

即使是强大的P/Invoke或者WebService,在遇到复杂的数据类型和大数据量的传递时,还是会碰到很大的困难。

因为,一种语言的复杂的数据类型,很难用另一种语言来表示。这就是跨平台调用问题的本质。

如,WEBService调用中,很多语言,如Java.NET都有自动实现的Java/.NET类型和XML类型之间的映射的类库或者工具。

但是,在现实的编程环境中,如果类型非常复杂,那么这些自动转换工具常常力不从心。

要么Object-XML映射错误。

要么映射掉大量的内存。

因此,我个人对这些Object-XML映射框架相当不感冒。

我现在使用WEBService,都是直接手工使用xml处理工具提取xml中的数据构建对象。或者反过来,手工根据Object中的属性值构建xml数据。

JavaC语言之间的调用问题,也是如此。

Java要调用C语言的函数,那么就必须严格按照C语言要求的内存数量提供Java格式的数据。要用Java的数据类型完美模拟C语言的数据类型。

JNA已经提供了大量的类型匹配C语言的数据类型。

跨平台、跨语言调用的第一原则:就是尽量使用基本、简单的数据类型,尽量少跨语言、平台传递数据!

只有你才能拯救你自己。

如果在你的程序中,有复杂的数据类型和庞大的跨平台数据传递。那么你必须另外写一些Façade接口,把需要传递的数据类型简化,把需要传递的数据量简化。

否则,不论是实现的难度还是程序的性能都很难提高。

JNI还是不能废

我们已经见识了JNA的强大。JNI和它相比是多么的简陋啊!

但是,有些需求还是必须求助于JNI

JNA是建立在JNI技术基础之上的一个框架。

使用JNI技术,不仅可以实现Java访问C函数,也可以实现C语言调用Java代码。

JNA只能实现Java访问C函数,作为一个Java框架,自然不能实现C语言调用Java代码。此时,你还是需要使用JNI技术。

JNIJNA的基础。是JavaC互操作的技术基础。

 

分享到:
评论

相关推荐

    jna-4.5.1 , jna-4.5.1-sources , jna-platform-4.5.1 jar包

    jna-4.5.1 , jna-4.5.1-sources , jna-platform-4.5.1 jar包 JNA全称Java Native Access,是一个建立在经典的JNI技术之上的Java开源框架(https://github.com/twall/jna)。JNA提供一组Java工具类用于在运行期动态...

    jna-4.1.0-API文档-中文版.zip

    赠送jar包:jna-4.1.0.jar; 赠送原API文档:jna-4.1.0-javadoc.jar; 赠送源代码:jna-4.1.0-sources.jar; 赠送Maven依赖信息文件:jna-4.1.0.pom; 包含翻译后的API文档:jna-4.1.0-javadoc-API文档-中文(简体)版...

    jna-4.3.0-API文档-中文版.zip

    赠送jar包:jna-4.3.0.jar; 赠送原API文档:jna-4.3.0-javadoc.jar; 赠送源代码:jna-4.3.0-sources.jar; 赠送Maven依赖信息文件:jna-4.3.0.pom; 包含翻译后的API文档:jna-4.3.0-javadoc-API文档-中文(简体)版...

    jna-5.5.0.jar中文文档.zip

    # 【jna-***.jar中文文档.zip】 中包含: 中文文档:【jna-***-javadoc-API文档-中文(简体)版.zip】 jar包下载地址:【jna-***.jar下载地址(官方地址+国内镜像地址).txt】 Maven依赖:【jna-***.jar Maven依赖...

    jna-5.4.0.jar中文文档.zip

    # 【jna-***.jar中文文档.zip】 中包含: 中文文档:【jna-***-javadoc-API文档-中文(简体)版.zip】 jar包下载地址:【jna-***.jar下载地址(官方地址+国内镜像地址).txt】 Maven依赖:【jna-***.jar Maven依赖...

    jna-4.5.0.jar中文文档.zip

    # 【jna-***.jar中文文档.zip】 中包含: 中文文档:【jna-***-javadoc-API文档-中文(简体)版.zip】 jar包下载地址:【jna-***.jar下载地址(官方地址+国内镜像地址).txt】 Maven依赖:【jna-***.jar Maven依赖...

    jna-5.0.0.jar中文文档.zip

    # 【jna-***.jar中文文档.zip】 中包含: 中文文档:【jna-***-javadoc-API文档-中文(简体)版.zip】 jar包下载地址:【jna-***.jar下载地址(官方地址+国内镜像地址).txt】 Maven依赖:【jna-***.jar Maven依赖...

    jna-4.0.0.jar中文文档.zip

    # 【jna-***.jar中文文档.zip】 中包含: 中文文档:【jna-***-javadoc-API文档-中文(简体)版.zip】 jar包下载地址:【jna-***.jar下载地址(官方地址+国内镜像地址).txt】 Maven依赖:【jna-***.jar Maven依赖...

    jna-4.5.2.jar中文文档.zip

    # 【jna-***.jar中文文档.zip】 中包含: 中文文档:【jna-***-javadoc-API文档-中文(简体)版.zip】 jar包下载地址:【jna-***.jar下载地址(官方地址+国内镜像地址).txt】 Maven依赖:【jna-***.jar Maven依赖...

    jna-4.4.0.jar中文文档.zip

    # 【jna-***.jar中文文档.zip】 中包含: 中文文档:【jna-***-javadoc-API文档-中文(简体)版.zip】 jar包下载地址:【jna-***.jar下载地址(官方地址+国内镜像地址).txt】 Maven依赖:【jna-***.jar Maven依赖...

    jna-5.5.0-API文档-中英对照版.zip

    赠送jar包:jna-5.5.0.jar 赠送原API文档:jna-5.5.0-javadoc.jar 赠送源代码:jna-5.5.0-sources.jar 包含翻译后的API文档:jna-5.5.0-javadoc-API文档-中文(简体)-英语-对照版.zip 对应Maven信息:groupId:...

    jna-5.10.0.jar中文文档.zip

    # 【jna-***.jar中文文档.zip】 中包含: 中文文档:【jna-***-javadoc-API文档-中文(简体)版.zip】 jar包下载地址:【jna-***.jar下载地址(官方地址+国内镜像地址).txt】 Maven依赖:【jna-***.jar Maven依赖...

    jna-5.6.0.jar中文文档.zip

    # 【jna-***.jar中文文档.zip】 中包含: 中文文档:【jna-***-javadoc-API文档-中文(简体)版.zip】 jar包下载地址:【jna-***.jar下载地址(官方地址+国内镜像地址).txt】 Maven依赖:【jna-***.jar Maven依赖...

    jna-4.2.2 官方原版下载

    Most simple questions will be answered on the list, but more complicated work, new features or target platforms can be negotiated with any of the JNA developers (this is how several of JNA's features...

    jna-platform-5.10.0-API文档-中英对照版.zip

    赠送jar包:jna-platform-5.10.0.jar; 赠送原API文档:jna-platform-5.10.0-javadoc.jar; 赠送源代码:jna-platform-5.10.0-sources.jar; 赠送Maven依赖信息文件:jna-platform-5.10.0.pom; 包含翻译后的API文档...

    JNA最新源文件jar包

    JNA(Java Native Access)框架是一个开源的Java框架,是SUN公司主导开发的,建立在经典的JNI的基础之上的一个框架。使用JNI调用共享类库(.dll/.so文件)是非常麻烦的事情,既需要编写java代码,又要编写C语言的代理...

    jna-5.10.0-API文档-中英对照版.zip

    赠送jar包:jna-5.10.0.jar; 赠送原API文档:jna-5.10.0-javadoc.jar; 赠送源代码:jna-5.10.0-sources.jar; 赠送Maven依赖信息文件:jna-5.10.0.pom; 包含翻译后的API文档:jna-5.10.0-javadoc-API文档-中文...

    JNA-5.7.0 jna-platform-5.7.0

    JNA-5.7.0 jna-platform-5.7.0

    jna.rar_ jna win32-x86.jar_function java_jna examples.jar_jna.ja

    JNA(Java Native Access )提供一组Java工具类用于在运行期动态访问系统本地库(native library:如Window的dll)而不需要编写任何Native/JNI代码。开发人员只要在一个java接口中描述目标native library的函数与...

    jna-5.9.0.jar

    2021 最新JNA jar包,jna-5.9.0

Global site tag (gtag.js) - Google Analytics