本节讲的是在 C/C++本地代码中创建Java对象,JNI 中提供两个方法进行Java对象的操作,分别是 NewObject 和 Allocobject,先看下jni.h 头文件中对两个方法的定义
jobject NewObject(jclass clazz, jmethodID methodID, ...) {
va_list args;
jobject result;
va_start(args, methodID);
result = functions->NewObjectV(this,clazz,methodID,args);
va_end(args);
return result;
}
jobject AllocObject(jclass clazz) {
return functions->AllocObject(this,clazz);
}
1、NewObject 创建Java对象
GetMethodID 能够获取构造方法的jmethod,如果传入的要取得的方法名称设定为”<init>”就能取得构造方法构造方法没有返回值,签名始终为Void (()V)
下面是一个通过C++创建Java的Date对象并在Java控制台输出1970到现在毫秒数
package com.fomagic;
public class TestNative {
public native void sayHello(); // C++本地代码实现
public static void main(String[] args) {
System.loadLibrary("NativeCode");// 加载动态链接库,不能加 .dll
TestNative test = new TestNative();
test.sayHello();
}
}
C++
JNIEXPORT void JNICALL Java_com_fomagic_TestNative_sayHello (JNIEnv *env, jobject obj)
{
jclass clazz_date = env->FindClass("java/util/Date"); //找到Date类
jmethodID id_date= env->GetMethodID(clazz_date,"<init>","()V"); //通过类获取构造方法ID,默认无返回值
jobject now=env->NewObject(clazz_date,id_date); //创建Date的实例对象
jmethodID id_date_getTime=env->GetMethodID(clazz_date,"getTime","()J"); //获取Date类的getTime()方法的ID,返回值是long 即 JNI中对应的 J
jlong time = env->CallLongMethod(now,id_date_getTime); //通过now对象调用getTime()方法,得到时间
cout<<time<<endl;
}
代码很简单通过前面的知识都是可以明白的,注释应该没什么问题(吧)
2、Allocobject创建Java对象
使用函数AllocObject 可以根据传入的jclass创建一个Java对象
但他的状态是非初始化的,在使用这个对象之前绝对要用CallNovirtualVoidMethod
来调用该jclass的建构函数,这样可以延迟构造函数的调用,这一部分用的很少
(对于这个函数到底是什么意思,我也没有完全搞明白,只是知道这样用,以后慢慢研究)
jclass clazz_str =env->FindClass("java/lang/String");
jmethodID methodID_str=env->GetMethodID(clazz_str,"<init>","([C)V");//获取构造方法ID
jObject string =env->AllocObject(clazz_str);// 预先创建没有初始化的字符串
jcharArray arg=env->NewCharArray(4); //创建长度为4的字符数组
env->SetCharArrayRegion(arg,0,4,L"奇幻未来"); //复制"奇幻未来"到数组arg中
env->CallNonvirtualVoidMethod(string,clazz_str,methodID_str,arg); //讲arg字符数组复制给string
jclass clazz_this=env->GetObjectClass(obj);
// 这是视频中假设这个对象的类中有定义 static String STATIC_STR;
jfieldID fieldID_str=env->GetStaticFieldID(clazz_this,"STATIC_STR","Ljava/lang/String;");
env->SetStaticObjectField(clazz_str,fieldID_str,string);