JNI(在C程序中运行Java类)
C/C++代码中调用Java代码的几种典型情况
- 需要在C/C++编写的本地应用程序中访问用Java语言编写的代码或代码库
- 希望在C/C++编写的本地应用程序中使用标准Java类库
- 当需要把已有的C/C++程序与Java程序组织链接在一起时,使用Invocation API,可以将它们组织成一个完整的程序
应用示例步骤
- 使用Invocation API加载Java虚拟机
- 加载Java类
- 执行被加载类的方法
- 销毁Java虚拟机
应用示例代码
InvocationApiTest.java
public class InvocationApiTest
{
public static void main(String[] args)
{
System.out.println(args[0]);
}
}
invocationApi.c
#include <jni.h>
int main()
{
JNIEnv *env;
JavaVM *vm;
JavaVMInitArgs vm_args;
JavaVMOption options[1];
jint res;
jclass cls;
jmethodID mid;
jstring jstr;
jclass stringClass;
jobjectArray args;
//生成Java虚拟机选项
options[0].optionString = "-Djava.class.path=.";
vm_args.version = 0x00010002;
vm_args.options = options;
vm_args.nOptions = 1;
vm_args.ignoreUnrecognized = JNI_TRUE;
//生成Java虚拟机
res = JNI_CreateJavaVM(&vm,(void**)&env,&vm_args);
//查找并加载类
cls = (*env)->FindClass(env,"InvocationApiTest");
//获取main()方法的ID
mid = (*env)->GetStaticMethodID(env,cls,"main","([Ljava/lang/String;)V");
//生成字符串对象,用作main()方法的参数
jstr = (*env)->NewStringUTF(env,"Hello Invocation API!!");
stringClass = (*env)->FindClass(env,"java/lang/String");
args = (*env)->NewObjectArray(env,1,stringClass,jstr);
// //调用main()方法
(*env)->CallStaticVoidMethod(env,cls,mid,args);
//销毁Java虚拟机
(*vm)->DestroyJavaVM(vm);
}
编译命令
gcc invocationApi.c "C:\Program Files\Java\jdk1.8.0_73\lib\jvm.lib" -lstdc++ -o invocationApi.exe
运行命令
invocationApi.exe
结果
Hello Invocation API!!
创建虚拟机
在生成Java虚拟机选项时,使用的JavaVMInitArgs与JavaVMOption结构体,它们定义在jni.h头文件中
typedef struct JavaVMOption {
char *optionString;
void *extraInfo;
} JavaVMOption;
typedef struct JavaVMInitArgs {
jint version;//版本号设置
jint nOptions;//JavaVMOption结构体数组元素个数
JavaVMOption *options;//JavaVMOption结构体的地址
jboolean ignoreUnrecognized;//虚拟中读到错误设置是否忽略错误继续执行
} JavaVMInitArgs;
JavaVMOption结构体用来指定Java虚拟机的选项值,其形式为-D<property>=<value>
JNI_CreateJavaVM
形式:
jint JNI_CreateJavaVM(JavaVM **vm,JNIEnv **env,void *vm_args)
说明:
装载并初始化Java虚拟机参数:
- vm JavaVM指针的地址
- env JNI接口指针的地址
- vm_args 传递给Java虚拟机的参数
返回值:
成功,返回0,失败,返回负值
创建数组
NewObjectArray
形式
jarray NewObjectArray(JNIEnv *env,jsize length,jclass elementClass,jobject initalElement)
说明:
生成由elementClass对象组成的数组。数组元素个数由length指定,initalElement参数用来初始化对象数组参数:
- env JNI接口指针
- length 数组元素个数
- elementClass 数组元素对象的类型
- initialElement 数组初始化值
返回值:
若成功,则返回数组引用,失败,则返回NULL
字符串转换
NewStringUTF
形式:
jstring NewStringUTF(JNIEnv *env,const char *bytes)
说明:
将UTF-8形式的C字符串转换成java.lang.String对象参数:
- env JNI接口指针
- bytes 待生成String对象的C字符串的地址
返回值:
成功,返回String对象的jstring类型的引用,失败,返回NULL
GetStringUTFChars
形式:
const jbyte*GetStringUTFChars(JNIEnv *env,jstring string,jboolean *isCopy)
说明:
将Java字符串对象转换成UTF-8字符串(C字符串),并返回指针参数:
- env JNI接口指针
- string Java字符串对象
- isCopy 当String对象中的字符串被转换成UTF-8字符串,被复制到内存,且指针被返回时,*isCopy 设置为JNI_TRUE,否则设置为JNI_FALSE