1 C访问Java非静态成员变量
c代码
JNIEXPORT jstring JNICALL Java_com_yeliang_JniTest_accessField(JNIEnv *env, jobject jobj){
//在java中新建JniTest对象 JniTest jniTest = new JniTest();
//1 根据jobject获得jclass对象 jobj是jniTest对象
jclass cls = (*env)->GetObjectClass(env, jobj);
//2 获得成员变量 jfieldID
jfieldID field = (*env)->GetFieldID(env, cls, "field", "Ljava/lang/String;");
//yeliang -->Mr yeliang 修改变量名字
//3 获取field属性的值 Get<Type>Field
jstring jstr = (*env)->GetObjectField(env, jobj, field);
//printf("jstr:%#x\n", &jstr);
//jstring->c字符串
//4 根据field的值重新定义一个char对象 isCopy 是否赋值 (true代表复制 false代表不复制)
char *c_str = (*env)->GetStringUTFChars(env, jstr, JNI_FALSE);
//5 拼接得到的新字符串
char text[20] = "super ";
strcat(text, c_str);
//6 根据字符数组重新生成字符串 c字符串 -> jstring
jstring new_jstr = (*env)->NewStringUTF(env,text);
//7 修改java中的field
(*env)->SetObjectField(env,jobj,field,new_jstr);
//printf("new_jstr:%#x\n",&new_jstr);
return new_jstr;
};
java代码
public native String accessField();
public String field = "yeliang";
public static void main(String[] args) {
JniTest jniTest = new JniTest();
System.out.println("jni修改前属性值为field="+jniTest.field);
jniTest.accessField();
System.out.println("jni修改后属性值为field="+jniTest.field);
}
打印结果
jni修改前属性值为field=yeliang
jni修改后属性值为field=super yeliang
2 C访问Java静态成员变量
c代码
JNIEXPORT void JNICALL Java_com_yeliang_JniTest_accessStaticField(JNIEnv *env, jobject jobj){
//1 根据jobject获得jclass
jclass cls = (*env)->GetObjectClass(env,jobj);
//2 获得jfieldID
jfieldID fieldId = (*env)->GetStaticFieldID(env,cls,"count","I");
//3 GetStatic<Type>Field
jint count = (*env)->GetStaticIntField(env,cls,fieldId);
count++;
//4 修改
(*env)->SetStaticIntField(env,cls,fieldId,count);
};
java代码
public native String accessStaticField();
private static int count = 5;
public static void main(String[] args) {
JniTest jniTest = new JniTest();
System.out.println("jni修改前属性值为count = "+jniTest.count);
jniTest.accessStaticField();
System.out.println("jni修改后属性值为count = "+jniTest.count);
}
打印结果
jni修改前属性值为count = 5
jni修改后属性值为count = 6
3 C访问java方法
c代码
JNIEXPORT void JNICALL Java_com_yeliang_JniTest_accessMethod
(JNIEnv *env, jobject jobj){
//1 获取jclass 类似java中的反射
jclass cls = (*env)->GetObjectClass(env,jobj);
//2 根据方法名和参数找到jmethodID
jmethodID mid = (*env)->GetMethodID(env,cls,"getRandomInt","(I)I");
//3 调用java中的方法
jint random = (*env)->CallIntMethod(env,jobj,mid,200);
printf("random num:%ld",random);
};
其中的
jmethodID mid = (*env)->GetMethodID(env,cls,"getRandomInt","(I)I");
中的I表示数据类型的签名
数据类型对应的签名是
java代码
public native void accessMethod();
public static void main(String[] args) {
JniTest jniTest = new JniTest();
jniTest.accessMethod();
}
public int getRandomInt(int range){
System.out.println("Java中的方法执行了");
return new Random().nextInt(range);
}
打印结果
Java中的方法执行了
random num:163
4 C访问java静态方法
c代码
JNIEXPORT void JNICALL Java_com_yeliang_JniTest_accessStaticMethod(JNIEnv *env, jobject jobj){
//1 jclass
jclass cls = (*env)->GetObjectClass(env,jobj);
//2 jmethodID
jmethodID mid = (*env)->GetStaticMethodID(env, cls, "getUUID", "()Ljava/lang/String;");
//3 调用java方法
jstring uuid = (*env)->CallStaticObjectMethod(env,cls,mid);
//4 接收java方法返回的uuid字符串
char *uuid_str = (*env)->GetStringUTFChars(env,uuid,JNI_FALSE);
//5 字符串拼接 获得文件名
char filename[100];
sprintf(filename,"D://%s.txt",uuid_str);
FILE *fp = fopen(filename,"w");
//6 字文件中写入数据
fputs("to be number one",fp);
fclose(fp);
};
java代码
public native void accessStaticMethod();
public static void main(String[] args) {
JniTest jniTest = new JniTest();
jniTest.accessStaticMethod();
}
public static String getUUID(){
System.out.println("Java中的方法执行了");
return UUID.randomUUID().toString();
}
打印结果:
Java中的方法执行了
并在D盘中生成了文件: