Java本地接口(Java Native Interface (JNI))允许运转在Java虚拟机(Java Virtual Machine (JVM))上的代码调用本地顺序和类库,或许被它们调用,这些顺序和类库可以是其它语言编写的,比如C、C++或许汇编语言。
当一个顺序无法完全使用Java编写时,开发者可以通过JNI来编写本地办法,比如规范Java类库并不支持的依赖于平台的特征或许顺序库。JNI还可以用于修改现有的使用其它语言编写的顺序,使它们可以通过Java编写的顺序来访问。
很多基本类库都依赖JNI来为开发者和用户提供服务,比如文件的输入/输入和音频功能。在基本类库中包含的对于性能战争台敏感的API可以允许一切的Java顺序以安全战争台有关的方式来使用这些功能,在采用JNI之前,开发者需求明确这些功能并不是曾经包含在Java规范类库中的,在这篇文章中,我将会解说JNI是如何任务的以及本地类型是如何映射到Java的类型和类库的。
JNI任务原理
在JNI中,本地函数是通过一个独立的.c或.cpp文件来完成的(C++为JNI提供的界面会更简洁一些)。当JVM调用该函数时,它传递了一个JNIEnv指针、一个jobject指针和通过Java办法定义的Java参数,JNI函数的形式如下:
JNIEXPORT void JNICALL Java_ClassName_MethodName
(JNIEnv *env, jobjectobj)
{
//Method native implemenation
}
env指针是一个包含了JVM接口的结构,它包含了与JVM停止交互以及与Java对象协同任务所必需的函数,示例中的JNI函数可以在本地数组和Java数组类型之间、本地字符串和Java字符串类型之间停止转换,其功能还包括对象的实例化、抛出异常等。基本上您可以使用JNIEnv来完成一切Java能做到的事情,虽然要简单很多。
更加正式的解释是这样的,本地代码通过调用JNI的函数来访问JVM,这是通过一个界面指针完成的(界面指针实际上是指向指针的指针),该指针指向一个指针数组,数组中的每个指针都指向了一个界面函数,而每个界面函数都是在数组中预先定义过的。
本地办法将JNI界面指针当作一个参数,假设在同一个Java线程中,出现对该本地办法的多重调用,JVM则保证传递相反的界面指针到本地办法。不过,一个本地办法可以被不同的Java线程调用,因而也可能会收到不同的JNI界面指针。
本地办法是通过System.loadLibrary办法加载的,在以下的例子中,类的初始化办法加载了一个指定平台的本地类库,该类库定义了本地办法:
packagepkg;
class Cls {
native double f(inti, String s);
static {
System.loadLibrary(pkg_Cls");
}
}
System.loadLibrary办法的参数是一个类库的名称,它可以由顺序员恣意选取,零碎则遵照一个规范的本地化平台的方式来转换类库的名称到一个本地类库的名称。例如,在Solaris操作零碎中会将pkg_Cls转换为libpkg_Cls.so,而Win32零碎则会将同样的pkg_Cls转换为pkg_Cls.dll。
静态指针会依据它们的名字来停止解析,一个本地办法的名称是按照组件停止衔接的,它包含了:前缀“Java_”、一个分离的合法的类名称和一个分离的办法名称。
注意:微软的JVM有相反的机制从Java调用本地Windows代码,该机制被称为原始本地接口(Raw Native Interface (RNI))。
数据类型映射
基本类型,比如整型、字符等等,是在Java和本地代码间停止拷贝的,而其他的自定义Java对象则是通过援用来传递的。
这个表格展示了Java和本地代码之间的类型映射,这些类型是可以互换的,您可以在您使用int类型的位置使用jint类型,
搜奇乐当然反过来也一样,而且不需求任何类型转化。但是,Java的字符串和数组类型和本地的字符串与数组类型之间的转换就比拟困难了,假设您使用的jstring类型中出现了字符“*”,您的代码会造成JVM的崩溃,以下的例子阐明了您应当如何正确使用字符串:
JNIEXPORT void JNICALL Java_ClassName_MethodName
(JNIEnv *env, jobjectobj, jstringjavaString)
{
//Get the native string from Java string
const char *nativeString = env-GetStringUTFChars(env,javaString, 0);
printf("%s", nativeString);
env-ReleaseStringUTFChars(env,javaString, nativeString);
}
您需求使用界面指针env来操作Java对象。
总结
在您的顺序中使用JNI并不是一件容易的事情,但是,JNI的性能和使用原有代码的能力将会为您的Java顺序添加更多的功能并且能胜任更多的应战,假设需求关于JNI的更多信息,可以访问JNI的主页。