给大家介绍一个最新的访问本机代码的
Java
框架
—JNA
。
JNA(Java Native Access)
框架是一个开源的
Java
框架,是
SUN
公司主导开发的,建立在经典的
JNI
的基础之上的一个框架。
JNA
项目地址:
https://jna.dev.java.net/
非常强大、易用,功能上类似与
.NET
的
P/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
语言在客户端上乏善可陈。可以说
JNI
是
Java
的一大弱点!
.NET
平台上强大的
P/Invoke
而在
.NET
平台上,强大的
P/Invoke
技术使我们
Java
程序员非常羡慕。使用
P/Invoke
技术,只需要使用编写一个
.NET
函数,再加上一个声明的标注,就可以直接调用
dll
中的函数。
不需要你再使用
C
语言编写
dll
来适配。
不逊于
P/Invoke
的
JNA
现在,不需要再羡慕
.NET
的
P/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
了。
为了方便你参考
JNA
的
java
类库,我制作了《
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;
/** Simple example of native library declaration and usage. */
public class HelloWorld {
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary)
Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"),
CLibrary.class);
void printf(String format, Object... args);
}
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]);
}
}
}
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);
这个函数的实现是:
void
say(
wchar_t
* pValue){
std::wcout.imbue(std::locale(
"chs"
));
std::wcout<<L
"上帝说:"
<<pValue<<std::endl;
}
它需要传入一个
Unicode
编码的字符数组。然后在控制台上打印出一段中文字符。
3
,生成
dll
。然后把生成的
dll
文件复制到
Eclipse
项目中,放在项目下面。
4
,在
Eclipse
中编写以下代码:
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
语言编写的转发器,可以自动实现
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
|
转载:
http://blog.csdn.net/shendl/archive/2008/12/23/3589676.aspx
JNA—JNI终结者.rar (89.1 KB)