Java中的静态方法和成员方法可以标记为本地方法,以指示在共享库文件中可以找到它们的实现。执行本机方法后,JVM使用简单的名称处理方案在已加载的库中查找相应的功能(请参阅加载本机库),执行参数转换和堆栈设置,然后将控制权移交给本机代码。
/*** com/example/jni/JNIJava.java **/ package com.example.jni; public class JNIJava { static { System.loadLibrary("libJNI_CPP"); } // 显然,本机方法可能没有用Java定义的主体 public native void printString(String name); public static native double average(int[] nums); public static void main(final String[] args) { JNIJava jniJava = new JNIJava(); jniJava.printString("Invoked C++ 'printString' from Java"); double d = average(new int[]{1, 2, 3, 4, 7}); System.out.println("Got result from C++ 'average': " + d); } }
包含本机函数声明的头文件应使用该javah工具在目标类上生成。在构建目录中运行以下命令:
javah -o com_example_jni_JNIJava.hpp com.example.jni.JNIJava
...产生以下头文件(为简洁起见,删除了注释):
// com_example_jni_JNIJava.hpp /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> // JNI API声明 #ifndef _Included_com_example_jni_JNIJava #define _Included_com_example_jni_JNIJava #ifdef __cplusplus extern "C" { // 如果使用C ++编译器,这是绝对必要的 #endif JNIEXPORT void JNICALL Java_com_example_jni_JNIJava_printString (JNIEnv *, jobject, jstring); JNIEXPORT jdouble JNICALL Java_com_example_jni_JNIJava_average (JNIEnv *, jclass, jintArray); #ifdef __cplusplus } #endif #endif
这是一个示例实现:
// com_example_jni_JNIJava.cpp #include <iostream> #include "com_example_jni_JNIJava.hpp" using namespace std; JNIEXPORT void JNICALL Java_com_example_jni_JNIJava_printString(JNIEnv *env, jobject jthis, jstring string) { const char *stringInC = env->GetStringUTFChars(string, NULL); if (NULL == stringInC) return; cout << stringInC << endl; env->ReleaseStringUTFChars(string, stringInC); } JNIEXPORT jdouble JNICALL Java_com_example_jni_JNIJava_average(JNIEnv *env, jclass jthis, jintArray intArray) { jint *intArrayInC = env->GetIntArrayElements(intArray, NULL); if (NULL == intArrayInC) return -1; jsize length = env->GetArrayLength(intArray); int sum = 0; for (int i = 0; i < length; i++) { sum += intArrayInC[i]; } env->ReleaseIntArrayElements(intArray, intArrayInC, 0); return (double) sum / length; }输出结果
运行上面的示例类将产生以下输出:
从Java调用C ++'printString'
得到C ++'average'的结果:3.4