- 创建带native的Java类 eg:Sample1.java
class Sample1 {
// --- Native methods
public native int intMethod(int n);
public native boolean booleanMethod(boolean bool);
public native String stringMethod(String text);
public native int intArrayMethod(int[] intArray);
// --- Main method to test our native library
public static void main(String[] args) {
System.loadLibrary("Sample1");
Sample1 sample = new Sample1();
int square = sample.intMethod(5);
boolean bool = sample.booleanMethod(true);
String text = sample.stringMethod("java");
int sum = sample.intArrayMethod(new int[] {1, 1, 2, 3, 5, 8, 13});
System.out.println("intMethod: " + square);
System.out.println("booleanMethod: " + bool);
System.out.println("stringMethod: " + text);
System.out.println("intArrayMethod: " + sum);
}
}
2. 保存编译, 会生成Sample1.class
javac Sample1.java
3. 使用javah 命令生成头文件,此时会出现 Sample1.h文件
javah Sample1
//Sample1.h文件内容为:
* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Sample1 */
#ifndef _Included_Sample1
#define _Included_Sample1
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: Sample1
* Method: intMethod
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_Sample1_intMethod
(JNIEnv *, jobject, jint);
/*
* Class: Sample1
* Method: booleanMethod
* Signature: (Z)Z
*/
JNIEXPORT jboolean JNICALL Java_Sample1_booleanMethod
(JNIEnv *, jobject, jboolean);
/*
* Class: Sample1
* Method: stringMethod
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_Sample1_stringMethod
(JNIEnv *, jobject, jstring);
/*
* Class: Sample1
* Method: intArrayMethod
* Signature: ([I)I
*/
JNIEXPORT jint JNICALL Java_Sample1_intArrayMethod
(JNIEnv *, jobject, jintArray);
#ifdef __cplusplus
}
#endif
#endif</jni.h>
4. 创建本地实现,新建C源码文件,Sample1.cpp
#include "Sample1.h"
#include <ctype.h>
#include <string.h>
// Mutate array to uppercase
void uppercase(char* str) {
size_t n = strlen(str);
for (size_t i = 0; i < n; i++) {
str[i] = toupper(str[i]);
}
}
JNIEXPORT jint JNICALL Java_Sample1_intMethod
(JNIEnv* env, jobject obj, jint num) {
return num * num;
}
JNIEXPORT jboolean JNICALL Java_Sample1_booleanMethod
(JNIEnv* env, jobject obj, jboolean boolean) {
return !boolean;
}
JNIEXPORT jstring JNICALL Java_Sample1_stringMethod
(JNIEnv* env, jobject obj, jstring string) {
const char* str = env->GetStringUTFChars(string, 0);
char cap[128];
strcpy(cap, str);
env->ReleaseStringUTFChars(string, str);
uppercase(cap);
return env->NewStringUTF(cap);
}
JNIEXPORT jint JNICALL Java_Sample1_intArrayMethod
(JNIEnv* env, jobject obj, jintArray array) {
int sum = 0;
jsize len = env->GetArrayLength(array);
jint* body = env->GetIntArrayElements(array, 0);
for (int i = 0; i < len; i++) {
sum += body[i];
}
env->ReleaseIntArrayElements(array, body, 0);
return sum;
}
5. 接下来对c++文件进行编译,生成函数库。库有静态库和动态库之分。静态库是以.a结尾的文件,例如:libXXX.a;动态库是以.so结尾的文件,例如: libXXX.so
比如,要编译生成动态链接库时:
gcc -c -fpic Sample1.cpp //会生成Sample1.o的中间文件
gcc -shared Sample1.o -o libSample1.so
//或者直接;
gcc -fpic -shared Sample1.c -o libSample1.so
完成之后就会生成动态链接库:libSample1.so
需要注意的是:
Java JNI的头文件 jni.h需要在两个地方包含:
其一:$JAVA_HOME/include
。
其二:$JAVA_HOME/include/linux
6.运行java程序:
//pwd 为包含libSample1.so文件的路径。
java -Djava.library.path=$(pwd) -cp . Sample1