public class JniTest2 {
//c访问非静态成员
public String testField="hello...";
//c修改java静态成员
public static int time=78;
//c访问java 方法
public native void invokeJavaMethod();
//c修改java 静态成员
public native void modifyStaField();
public native static String getProgress();
public native String getStringFromC();
public static void main(String[] args) {
// TODO Auto-generated method stub
String progress=getProgress();
System.out.println("test=from c="+progress);
JniTest2 t=new JniTest2();
System.out.println("test c before=="+t.testField);
String result=t.getStringFromC();
System.out.println("test c after=="+result);
System.out.println("===============静态成员修改==============");
System.out.println("test=c beforestatic="+time);
t.modifyStaField();
System.out.println("test=c after static="+time);
System.out.println("===============调用java方法==============");
t.invokeJavaMethod();
}
static {
//加载x64 .dll静态库
System.loadLibrary("JNIDateType");
}
public int generateRandom(int seed) {
System.out.println("test=java 方法被C调用了=");
return new Random().nextInt(seed);
}
}
下面是c/c++访问java 成员和方法
#define _CRT_SECURE_NO_WARNINGS
#include "jni_data_test_JniTest2.h"
#include<string.h>
//c返回java 层数据
JNIEXPORT jstring JNICALL Java_jni_1data_1test_JniTest2_getProgress
(JNIEnv *Env, jclass jcls){
//Java函数在c层实现
char *progress = "95";
return (*Env)->NewStringUTF(Env,progress);
};
//c重写实现java方法
JNIEXPORT jstring JNICALL Java_jni_1data_1test_JniTest2_getStringFromC
(JNIEnv *Env, jobject jobj){
//得到java 发射类
jclass jobjclass= (*Env)->GetObjectClass(Env,jobj);
//通过反射得到java 成员,注意最后一个参数是数据类型签名“L+类名(中间斜杠)”
jfieldID jfield = (*Env)->GetFieldID(Env, jobjclass, "testField", "Ljava/lang/String;");
//获取当前成员属性值
jstring jfieldvalue = (*Env)->GetObjectField(Env,jobj,jfield);
//注意:c无法修改jstring,进行转换char*,最后一个参数是否复制
char *fieldValue = (*Env)->GetStringUTFChars(Env, jfieldvalue, NULL);
strcat(fieldValue,"what the fuck!");
//char * 转成 jstring 返回
jstring result =(*Env)->NewStringUTF(Env,fieldValue);
//修改java的成员值
(*Env)->SetObjectField(Env,jobj,jfield,result);
return result;
};
//c 调用java 方法
JNIEXPORT void JNICALL Java_jni_1data_1test_JniTest2_invokeJavaMethod
(JNIEnv *Env, jobject jobj){
//反射java类
jclass javaclass=(*Env)->GetObjectClass(Env,jobj);
//获取方法id,方法签名 java工程bin目录 javap -s -p java全类名
jmethodID methodId=(*Env)->GetMethodID(Env,javaclass,"generateRandom","(I)I");
//调用方法
jint value=(*Env)->CallIntMethod(Env,jobj,methodId,89);
printf("c调用java方法结果==%d==\n",value);
};
//c 修改java静态成员
JNIEXPORT void JNICALL Java_jni_1data_1test_JniTest2_modifyStaField
(JNIEnv *Env, jobject jobj){
jclass javaclz= (*Env)->GetObjectClass(Env,jobj);
//注意成员签名
jfieldID staFieldId=(*Env)->GetStaticFieldID(Env,javaclz,"time","I");
//jint 是long类型,可强转
jint fieldValue= (*Env)->GetStaticIntField(Env,javaclz,staFieldId);
fieldValue += 15;
//修改完成设置static 成员
(*Env)->SetStaticIntField(Env,javaclz,staFieldId,fieldValue);
};
运行效果如下,工作空间GBK和UTF8不协调乱码
总结:其中最值得注意的是,获取java 类里面所有成员签名的命令方式
//签名,进入 java工程bin目录 javap -s -p java全类名
见如下图中标红的,就是java 类中的成员的签名
c/c++有很多方法是没有的但Java有的,如果c/c++自己实现起来很不方便,不如调用java现有的,这也是面向对象思想体现。