一、JNI简述
二、JNI基本类型
copy表一份,很详细的了!
Java类型
|
本地类型
|
描述
|
boolean
|
jboolean
|
C/C++8位整型
|
byte
|
jbyte
|
C/C++带符号的8位整型
|
char
|
jchar
|
C/C++无符号的16位整型
|
short
|
jshort
|
C/C++带符号的16位整型
|
int
|
jint
|
C/C++带符号的32位整型
|
long
|
jlong
|
C/C++带符号的64位整型
|
float
|
jfloat
|
C/C++32位浮点型
|
double
|
jdouble
|
C/C++64位浮点型
|
Object
|
jobject
|
任何Java对象,或者没有对应java类型的对象
|
Class
|
jclass
|
Class对象
|
String
|
jstring
|
字符串对象
|
Object[]
|
jobjectArray
|
任何对象的数组
|
boolean[]
|
jbooleanArray
|
布尔型数组
|
byte[]
|
jbyteArray
|
比特型数组
|
char[]
|
jcharArray
|
字符型数组
|
short[]
|
jshortArray
|
短整型数组
|
int[]
|
jintArray
|
整型数组
|
long[]
|
jlongArray
|
长整型数组
|
float[]
|
jfloatArray
|
浮点型数组
|
double[]
|
jdoubleArray
|
双浮点型数组
|
表2 Java类型映射
三、Java调用C&C++
1)Java类中编写native声明的方法。
2)javah命令生成JNI样式.h文件。
需要注意以下几点:1、JNI调用函数必须要用C编译器编译。也就是C++别忘了extern "C"那块;2、方法名格式:Java_pacakege_class_method。
例子程序的HelloJni.h文件:
#ifndef HELLOJNI_H_
#define HELLOJNI_H_
#include <jni.h>
// JNI调用函数必须要用C编译器编译
// C++不加extern "C",调用会有异常
#ifdef __cplusplus
extern "C" {
#endif
/*
* 1、JNIEXPORT、JNICALL:jni的宏
* 2、jstring:返回值类型(对应java的string)
* 3、C方法名:Java_pacakege_class_method
* 4、JNIEnv*、jobject:jni必要参数(jni环境、java对象)
*/
JNIEXPORT void JNICALL Java_org_join_jni_JniTest_sayHelloWin (JNIEnv*, jobject, int, int, int, int);
#ifdef __cplusplus
}
#endif
#endif /* HELLOJNI_H_ */
3)用C&C++方法实现本地方法,编译成动态库
4)Java类中用System.loadLibrary()或System.load()方法加载生成的dll文件
System.loadLibrary():装载Windows\System32下或
jre\bin或
Tomcat\bin目录下的本地链接库
System.load():根据具体的目录来加截本地链接库,必须是绝对路径
5)OK!
注意jni方法的使用,C&C++格式是不一样的,如下:
C 格式:(*env) -> <jni function> (env, <parameters>)
C++ 格式:env -> <jni function> (<parameters>)
返回jstring:return env->NewStringUTF("XXX");
另外数组类型的话,jni提供了操作的函数,稍复杂点,例子里没写也就不说了。
四、C&C++回调Java
直接看代码吧,每步都有注释了。
1)包org.join.jni下类JniTest内定义的两方法
/** C回调Java方法(静态) */
public static int add(int x, int y) {
System.out.println("==Java静态add方法==");
return x + y;
}
/** C回调Java方法(非静态) */
public int sub(int x, int y) {
System.out.println("==Java非静态sub方法==");
return x - y;
}
2)CallJava.h
#ifndef CALLJAVA_H_
#define CALLJAVA_H_
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
int add(JNIEnv*, int, int);
int sub(JNIEnv*, int, int);
jobject getInstance(JNIEnv*, jclass);
#endif /* CALLJAVA_H_ */
3)CallJava.cpp
#include "CallJava.h"
/**
* C回调Java方法(静态)
*/
int add(JNIEnv *env, int x, int y) {
// 获取类
jclass AnalyzeCidUtil = env->FindClass("org/join/jni/JniTest");
if (NULL == AnalyzeCidUtil) {
return -1;
}
// 获取类add静态方法
/*
* 第三个参数为方法签名
*
* 可用JDK自带工具javap生成该类所有方法签名
* 控制台进入该类class文件目录,输入:javap -s -private 类名
*/
jmethodID add = env->GetStaticMethodID(AnalyzeCidUtil, "add", "(II)I");
if (NULL == sub) {
env->DeleteLocalRef(AnalyzeCidUtil); // 删除类指引
return -2;
}
// 调用静态int方法
int result = env->CallStaticIntMethod(AnalyzeCidUtil, add, x, y);
// 返回结果
return result;
}
/**
* C回调Java方法(非静态)
*/
int sub(JNIEnv *env, int x, int y) {
// 获取类
jclass AnalyzeCidUtil = env->FindClass("org/join/jni/JniTest");
if (NULL == AnalyzeCidUtil) {
return -1;
}
// 实例化类对象
jobject mAnalyzeCidUtil = getInstance(env, AnalyzeCidUtil);
if (NULL == mAnalyzeCidUtil) {
env->DeleteLocalRef(AnalyzeCidUtil); // 删除类指引
return -2;
}
// 获取对象sub方法
jmethodID sub = env->GetMethodID(AnalyzeCidUtil, "sub", "(II)I");
if (NULL == sub) {
env->DeleteLocalRef(AnalyzeCidUtil); // 删除类指引
env->DeleteLocalRef(mAnalyzeCidUtil); // 删除类对象指引
return -3;
}
// 调用非静态int方法
int result = env->CallIntMethod(mAnalyzeCidUtil, sub, x, y);
// 返回结果
return result;
}
/**
* 实例化类对象
*/
jobject getInstance(JNIEnv *env, jclass clazz) {
// 获取构造方法
jmethodID constructor = env->GetMethodID(clazz, "<init>", "()V");
if (NULL == constructor) {
return NULL;
}
// 实例化类对象
return env->NewObject(clazz, constructor);
}
注意静态和非静态方法相差的实例化类对象的区别!