JNA

JNA(Java Native Access)是建立在JNI(Java Native Interface,Java本地调用)技术之上的Java开源框架,JNA提供了一组Java工具类用于在运行期间动态访问系统本地库(Native Library,如Windows的动态链接库*.dll、Linux的共享库*.so)。

使用JNA开发后无需编写任何Native/JNI代码,只需在Java接口中描述目标Native Library的函数与结构,JNA会自动实现Java接口到Native Library的映射,可以方便地使用Java直接访问动态链接库中的函数。

JNA提供了一个动态的C编写的转发器,可自动实现Java和C的数据类型映射。DLL和SO是C函数的集合和容器,这与Java中的接口概念吻合,JNA把DLL/SO文件看作是接口,在JNA中定义一个接口相当于定义了一个DLL/SO文件的描述文件,Java接口代表了动态链接库中发布的函数。

使用JNA一般只适用于简单的C/C++库,如果接口、数据结构复杂的化就不推荐,而且JNA也只提供了C/C++对Java的接口转化。

JNI

JNI全称Java Native Interface即Java本地调用,从Java1.1开始JNI标准成为Java平台的一部分,实现了Java代码和其他语言编写的代码交互。JNI实现Java跨平台的同时,也能与其他语言(如C、C++)的动态库交互。

使用JNI可以实现Java程序中的函数调用Native语言编写的函数,Native一般指的是C/C++编写的函数。使用JNI可以实现在Native程序的函数中调用Java层的函数,也就是在C/C++程序中可以调用Java函数。

JVM本身就是用Native语言编写的,JVM运行在具体平台上其本身是无法做到与平台无关的。通过JNI技术可以对Java层屏蔽具体JVM实现上的差异,进而实现Java本身的平台无关性。

使用JNI并不简单,对一个编译好的DLL/SO文件,使用JNI调用时首先需要使用C另外编写一个DLL/SO共享库,使用SUN规定的数据结构替代C的数据结构,再调用已有的DLL/SO中公布的函数。然后在Java中载入这个DLL/SO,最后编写Java Native函数作为链接库中函数的代理。使用JNI技术调用本地代码比较繁琐,因此引入了JNA技术。

使用JNI调用C/C++的过程

时序 步骤 文件类型
1 编写Java类代码 *.java
2 编译成字节码 *.class
3 产生C/C++头文件 *.h
4 编写JNI实现代码 *.c/cpp
5 编译成链接库文件 *.dll/so

使用JNA相比JNI调用动态链接库会有性能损耗,速度会降低几倍。另外,使用JNI不仅可以实现Java访问C函数,也可实现C调用Java代码。但JNA只能实现Java访问C函数。

入门

JNA定义的接口继承自com.sun.jna.Library接口,若DLL文件中的函数以stdcall方式输出,接口应继承com.sun.jna.win32.StdCallLibrary接口。

例如:在SpringBoot中是用DLL文件

  1. 创建Maven工程,将DLL文件放到resources目录下。
  2. 引入JNA相关的jar包
  3. 创建继承自Library类的接口
  4. 接口中创建对象用于加载DLL/SO的类库。
  5. 接口中声明DLL/SO类库头文件中暴露的方法

引入依赖

$ vim pom.xml
<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna</artifactId>
    <version>5.4.0</version>
</dependency>

JNA引入动态链接库

通过JNA建立与动态链接库的映射,只需创建一个接口来调用Native的loadLabrary()方法。

JNA建立与动态链接库中函数的对应关系,只需在加载相应类库接口中声明的函数即可。

JNA调用原生函数的模式

JNI中是用Native关键字来声明一个Java方法表明外部的原生函数,JNA中没有使用Native表明原生函数而是使用Java Interface来表明动态链接库中全部原生函数。

使用JNI加载动态链接库时必须使用System.loadLibrary()方法,将专门为JNI编写的动态链接库载入,这个动态链接库实际上是真正动态链接库的代理。使用JNA无需编写作为代理的动态链接库,直接使用JNA库的Native类中的loadLibrary()方法可直接加载最终的动态链接库。

类型映射

JNA使用的数据类型是Java的数据类型,而原生函数中是用的数据类型是原生函数编程语言的数据类型,大多为C/Delphi/汇编等语言的数据类型。如果数据类型映射不一致,调用时可能会发生无法预知的行为导致调用失败。

JNA的难点在于编程语言之间的数据类型不一致,Java中是用的函数必须与链接库中的函数的函数原型保持一致,这是JNA甚至是所有跨平台调用的难点,因为C/C++的类型与Java的类型是不一样的,因此必须将其装换为Java对应的数据类型,这就是类型映射(Type Mappings)。类型映射的难点在于结构体、指针和函数回调。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,039评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,223评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,916评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,009评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,030评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,011评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,934评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,754评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,202评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,433评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,590评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,321评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,917评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,568评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,738评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,583评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,482评论 2 352

推荐阅读更多精彩内容