JNI 入门
JNI 表示 Java Native Interface。它是一种如何从在 JVM 控制下运行的 Java 应用程序调用本机代码的机制,反之亦然。本机代码表示为目标平台编译的代码。本机代码通常用 C 或 C++编写,但它可以用任何具有目标平台编译器的语言编写。
JNI 非常有用
- Java 应用程序需要访问特定于平台的资源,并且没有具有所需功能的 Java 库。资源可以是特定的硬件,传感器或其他。
- Java 应用程序必须执行性能关键任务,本机代码可能比 java 字节码更快或占用空间更少。尽管如此,确实过于自信 JVM 能够进行大量的优化,而 C / C++中的天真实现可能会更慢。
- C / C++(或其他语言)中的应用程序想要使用 java 库中提供的功能。
从 JNI 开始,你需要
- JDK 或能够将 java 编译为字节码的东西。
- 用于编译本机代码的编译器。
以下 hello world 示例是一个调用 C 函数的简单 Java 应用程序。该示例可以由 javac 从 JDK 和 gcc C 编译器编译。
Java 代码:
public class JNIExample {
public static void main(String[] args) {
// The loadLibrary search for the native library (libnative.so in this case)
System.loadLibrary("native");
String s = "Hello JNI";
JNIExample example = new JNIExample();
example.doPrint(s);
}
// The method with native code (written in C) must be declared with native prefix
public native void doPrint(String message);
}
C 代码:
#include <jni.h>
#include <stdio.h>
/* the function that is called from java must be declered with decorators
* JNIEXPORT and JNICALL.
* The function name is constructed as Java_ClassName_MethodName
* Function parameters correspond parameters in java but there are 2 extra parameters
* JNIEnv is a pointer to java envoronmet and jobject is a reference to caller object.
* Caller object is the instance of the JNIExample in this case.
*/
JNIEXPORT void JNICALL Java_JNIExample_doPrint(JNIEnv *e, jobject obj, jstring message) {
const char *c_message;
/* It is necessary to convert java objects like string to something C native */
c_message = (*e)->GetStringUTFChars(e, message, NULL);
printf("%s\n", c_message);
/* in the end it is necessary to free resources allocated by Get above */
(*e)->ReleaseStringUTFChars(e, message, c_message);
}