JNA
技术解密
JNA
工作原理
JNA
是建立在
JNI
技术基础之上的一个
Java
类库,它使您可以方便地使用
java
直接访问动态链接库中的函数。
原来使用
JNI
,你必须手工用
C
写一个动态链接库,在
C
语言中映射
Java
的数据类型。
JNA
中,它提供了一个动态的
C
语言编写的转发器,可以自动实现
Java
和
C
的数据类型映射。你不再需要编写
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
接口。
Dll
是
C
函数的集合、容器,这正和接口的概念吻合。
我们定义这样一个接口,
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
的函数!
注意:
1
,
Native.loadLibrary()
函数有
2
个参数:
1
,
dll
或者
.so
文件的名字,但不带后缀名。这符合
JNI
的规范,因为带了后缀名就不可以跨操作系统平台了。
搜索
dll
的路径是:
1
)项目的根路径
2
)操作系统的全局路径、
3
)
path
指定的路径。
2
,第二个参数是本接口的
Class
类型。
JNA
通过这个
Class
类型,根据指定的
dll/.so
文件,动态创建接口的实例。
2
,接口中你只需要定义你需要的函数或者公共变量,不需要的可以不定义。
public void say(WString value);
参数和返回值的类型,应该和
dll
中的
C
函数的类型一致。
这是
JNA
,甚至所有跨平台调用的难点。
这里,
C
语言的函数参数是:
wchar_t
*
。
JNA
中对应的Java
类型是WStirng
。
所有跨平台、跨语言调用的难点
有过跨语言、跨平台开发的程序员都知道,跨平台、语言调用的难点,就是不同语言之间数据类型不一致造成的问题。绝大部分跨平台调用的失败,都是这个问题造成的。
关于这一点,不论何种语言,何种技术方案,都无法解决这个问题。
这需要程序员的仔细开发和设计。这是程序员的责任。
常见的跨平台调用有:
1
,
Java
调用
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
数据。
Java
和
C
语言之间的调用问题,也是如此。
Java
要调用
C
语言的函数,那么就必须严格按照
C
语言要求的内存数量提供
Java
格式的数据。要用
Java
的数据类型完美模拟
C
语言的数据类型。
JNA
已经提供了大量的类型匹配
C
语言的数据类型。
JNI
还是不能废
我们已经见识了
JNA
的强大。
JNI
和它相比是多么的简陋啊!
但是,有些需求还是必须求助于
JNI
。
JNA
是建立在
JNI
技术基础之上的一个框架。
使用
JNI
技术,不仅可以实现
Java
访问
C
函数,也可以实现
C
语言调用
Java
代码。
而
JNA
只能实现
Java
访问
C
函数,作为一个
Java
框架,自然不能实现
C
语言调用
Java
代码。此时,你还是需要使用
JNI
技术。
JNI
是
JNA
的基础。是
Java
和
C
互操作的技术基础。
分享到:
相关推荐
**标题:“JNA—JNI终结者”** 这篇文章探讨的主题是Java Native Access (JNA) 和 Java Native Interface (JNI),两者都是Java平台上的技术,用于在Java应用程序中调用本地(非Java)代码。它们允许Java程序员与...
### 使用JNA替代JNI调用DLL,并解决内存溢出问题 #### 问题背景 在项目的开发过程中,常常遇到需要处理二进制流数据并对其进行解析处理的情况。这种情况下,如果上层应用平台采用的是Java开发,而底层算法或数据...
《JNI与JNA在Spring Boot 2.3.0中的应用探索》 JNI(Java Native Interface)和JNA(Java Native Access)是Java平台中用于与本地代码交互的两种主要技术。它们允许Java应用程序调用C、C++等本地库,从而扩展Java的...
在这种情况下,"springboot+jna/jni调用动态so/dll库"是一个重要的主题,它涉及到Spring Boot应用如何利用Java Native Interface (JNI) 和 Java Native Access (JNA) 这两种技术来调用操作系统级别的动态链接库(.so...
这里我们主要探讨两种方式:JNI(Java Native Interface)和JNA(Java Native Access)。这两种技术允许Java代码与本地代码进行交互,使得Java开发者能够利用非Java编写的库或操作系统功能。 首先,JNI是Java平台...
JNI(Java Native Interface)和JNA(Java Native Access)都是Java平台上的原生接口技术,允许Java代码与操作系统底层交互,调用本地库。它们在功能上类似,但实现方式不同,因此性能也有所差异。 ### JNI JNI是...
JNI 和 JNA 的比较 尽管示例适用于所有平台,但 Makefile 仅适用于 Linux 和 OSX。 因此,这些是唯一受支持的平台 该存储库包含两个子项目,一个用于 JNI,一个用于 JNA。 实现的用例是 在 C 中生成一个随机数并从 ...
Java Native Access (JNA) 是一个非常实用的框架,它允许Java程序直接调用本地(Native)代码,无需编写JNI(Java Native Interface)代码。本案例将详细介绍如何使用JNA来调用C++动态库,特别是处理二维数组的输入和...
JNA—JNI终结者,java调用dll、ocx、so最简单的方法中提到的包 jna.jar
JNA(Java Native Access )提供一组Java工具类用于在运行期动态访问系统本地库(native library:如Window的dll)而不需要编写任何Native/JNI代码。开发人员只要在一个java接口中描述目标native library的函数与...
JNA(Java Native Access )提供一组Java工具类用于在运行期动态访问系统本地库(native library:如Window的dll)而不需要编写任何Native/JNI代码。开发人员只要在一个java接口中描述目标native ...是JNI终结者。
JNA3.09API参考手册.chm 是我制作的JNA类库3.09版的Java API参考手册。方便查找。 JNA是最新的Java平台上调用动态链接库.dll/.so的类库。是JNI终结者。
分别用JNI和JNA的方式建立dll,dll中包含一个get方法和一个set方法,在java端进行循环调用1000*1000次,比较所耗费的时间。 结论:JNI消耗的总时间(16ms) JNA消耗的总时间(2593ms) 性能:JNI >> JNA
在Java世界中,有时我们需要利用Java Native Interface (JNI) 和 Java Native Access (JNA) 这两种技术来调用C++编写的动态链接库(DLL或SO文件),以实现Java程序与底层系统的交互。这两者都是Java平台上的关键组件,...
研究java调用dll的时候,大部分都是通过jni,比较麻烦,我找到了通过jna方法调用dll的方法,用起来比较方便,只需要引用jna.jar包,这个jar包已经包含在程序中,还包含了我调用dll的遇到难道的解决办法。
步骤二:创建JNI接口定义 在Java源代码同目录下,创建一个`JniAdd.c`或`JniAdd.cpp`文件,定义JNI函数。这个文件将实现Java中声明的本地方法: ```c #include <jni.h> #include "JniAdd.h" JNIEXPORT jint JNICALL...
Java Native Access(JNA)是Java平台上的一个开源库,它允许Java代码直接调用操作系统提供的本地函数,而无需编写JNI(Java Native Interface)代码。JNI是Java与本机代码交互的标准方式,但它通常需要编写大量的C/...
Java Native Access(JNA)是Java平台上的一个开源库,它允许Java代码直接调用操作系统提供的原生函数,而无需编写任何C/C++代码或使用JNI(Java Native Interface)。JNA通过提供一种映射机制,将Java方法与本地库...
JNA提供一组Java工具类用于在运行期动态访问系统本地库(native library:如Window的dll)而不需要编写任何Native/JNI代码。开发人员只要在一个java接口中描述目标native library的函数与结构,JNA将自动实现Java...
Java Native Interface (JNI) 和 Java Native Access (JNA) 是两种主要的机制,允许Java代码调用C/C++函数。本篇文章将详细讲解如何在Android中使用JNA来调用C/C++方法。 首先,了解JNA的基本概念。JNA是一种轻量级...