native调用Java的普通属性
- Java 代码
public class JniUtils {
static{
System.loadLibrary("JNIEnvOne");
}
public String name = "liu";
//访问普通属性
public native void modifField();
}
- C 代码
//调用普通属性
JNIEXPORT void JNICALL Java_com_liu_JniUtils_modifField
(JNIEnv * env, jobject obj){
//获取类
jclass jclazz = (*env)->GetObjectClass(env, obj);
//获取属性,属性签名
jfieldID field = (*env)->GetFieldID(env, jclazz, "name", "Ljava/lang/String;");
//拿到属性的值(JNI的)
//get<Type>Field 模式,不同的类型
jstring jojb = (*env)->GetObjectField(env, obj, field);
//转成c的字符串
//isCopy 是否赋值的意思。
jboolean isCopy = NULL;
char* c_str = (*env)->GetStringChars(env, jojb, &isCopy);
if (isCopy){
printf("%s\n", "this str is copy");
}
char* mid = "I am from C";
//拼接C的字符串
strcat(c_str, mid);
//set<Type>Field 模式
(*env)->SetObjectField(env, obj, field, (*env)->NewStringUTF(env, c_str));
//释放
(*env)->ReleaseStringChars(env, jojb, c_str);
}
调用步骤:
- 获取类。 (*env)->GetObjectClass(env, obj);
- 获取属性签名。(*env)->GetFieldID(env, jclazz, “name”, “Ljava/lang/String;”);
- 拿到属性的值。(*env)->GetObjectField(env, obj, field);
- 把值转换成C可操作的类型。(*env)->GetStringChars(env, jojb, &isCopy);
- 操作属性的值。strcat(c_str, mid)/重新赋值等等
- 转换成JNI需要的类型。((*env)->NewStringUTF(env, c_str))
- 设置到属性里面。SetObjectField
- 把创建的字符串释放。(*env)->ReleaseStringChars(env, jojb, c_str);
native调用Java的静态属性
- Java 代码
public class JniUtils {
static{
System.loadLibrary("JNIEnvOne");
}
public static String staticName = "liu";
//访问静态属性
public native void modifStaticField();
}
- C 代码
//获取静态属性
JNIEXPORT void JNICALL Java_com_liu_JniUtils_modifStaticField
(JNIEnv * env, jobject obj){
//先获取jclass
jclass cls = (*env)->GetObjectClass(env, obj);
//获取属性签名
jfieldID fid = (*env)->GetStaticFieldID(env, cls, "staticName", "Ljava/lang/String;");
//获取属性
jstring field = (*env)->GetStaticObjectField(env, cls, fid);
//转换成c的类型
char* str = (*env)->GetStringChars(env, field, NULL);
char* s = "static str";
strcat(s, str);
jstring result = (*env)->NewStringUTF(env, s);
(*env)->SetStaticObjectField(env, cls, fid, result);
(*env)->ReleaseStringChars(env, field, str);
}
步骤:
- 获取类
- 获取属性签名
- 获取属性
- 转换成C可操作的类型
- 操作值
- 转换成JNI需要的类型
- 设置属性
- 释放资源
native调用Java的普通方法
- Java代码
public class JniUtils {
static{
System.loadLibrary("JNIEnvOne");
}
//访问普通方法
public native void callMethod(int count);
public void normalMethod(int count){
System.out.println("普通方法被调用了。count:"+count);
}
}
- C 代码
//调用普通方法
JNIEXPORT void JNICALL Java_com_liu_JniUtils_callMethod
(JNIEnv * env, jobject obj,jint count){
//获取类
jclass cls = (*env)->GetObjectClass(env, obj);
//获取方法签名
jmethodID mid = (*env)->GetMethodID(env, cls, "normalMethod", "(I)V");
//调用方法
(*env)->CallObjectMethod(env, obj, mid, count);
}
步骤:
- 获取类
- 获取方法签名
- 调用方法
native调用Java的静态方法
- Java 代码
public class JniUtils {
static{
System.loadLibrary("JNIEnvOne");
}
//访问静态方法
public native void callStaticMethod();
public static void staticMethod(){
System.out.println("static 方法被调用了。count:");
}
}
- C 代码
//调用静态方法
JNIEXPORT void JNICALL Java_com_liu_JniUtils_callStaticMethod
(JNIEnv * env, jobject obj, jint count){
//获取类
jclass cls = (*env)->GetObjectClass(env, obj);
//获取方法签名
jmethodID mid = (*env)->GetStaticMethodID(env, cls, "staticMethod", "()V");
//调用方法
(*env)->CallStaticVoidMethod(env, cls, mid);
}
Java层调用native,返回乱码问题及调用构造方法
- Java 代码
public class JniUtils {
static{
System.loadLibrary("JNIEnvOne");
}
//访问构造方法
public native void callConstructMethod();
public String name = "liu";
}
- C 代码
//解决字符串的乱码问题,及访问类的构造器
//通过new String(byte[],charset)。转换编码来解决乱码问题
jstring conv_str_to_java(JNIEnv* env, char* str){
//先找到类
jclass cls = (*env)->FindClass(env, "java/lang/String");
//获取构造器的方法签名
jmethodID mid = (*env)->GetMethodID(env, cls, "<init>", "([BLjava/lang/String;)V");
//需要转换的字符串长度
int arr_len = strlen(str);
//jbyte-char。初始化一个同等长度的字符数组
jbyteArray arr = (*env)->NewByteArray(env, arr_len);
//str数组赋值到jbytArray
(*env)->SetByteArrayRegion(env, arr, 0, arr_len, str);
//把需要的编码,转换成JNI需要的类型
jstring charsetName = (*env)->NewStringUTF(env, "GB2312");
//调用String的构造方法,初始化String类
jstring result = (*env)->NewObject(env, cls, mid, arr, charsetName);
return result;
}
//调用普通属性
JNIEXPORT void JNICALL Java_com_liu_JniUtils_callConstructMethod
(JNIEnv * env, jobject obj){
//获取类
jclass jclazz = (*env)->GetObjectClass(env, obj);
//获取属性,属性签名
jfieldID field = (*env)->GetFieldID(env, jclazz, "name", "Ljava/lang/String;");
//拿到属性的值(JNI的)
//get<Type>Field 模式,不同的类型
jstring jojb = (*env)->GetObjectField(env, obj, field);
//转成c的字符串
char* c_str = (*env)->GetStringChars(env, jojb,NULL);
char* mid = "我是C的字符串";
//拼接C的字符串
strcat(c_str, mid);
//set<Type>Field 模式
//这样是有乱码的
//(*env)->SetObjectField(env, obj, field, (*env)->NewStringUTF(env, c_str));
//通过上面的函数转换后,就没有乱码了
(*env)->SetObjectField(env, obj, field, conv_str_to_java(env,c_str));
//释放
(*env)->ReleaseStringChars(env, jojb, c_str);
}
native调用Java的普通的类的方法
- Java 代码
public class JniUtils {
static{
System.loadLibrary("JNIEnvOne");
}
//访问普通类的普通方法
public native long callNormalClassMethod();
}
- C 代码
//访问普通类的方法
JNIEXPORT jlong JNICALL Java_com_liu_JniUtils_callNormalClassMethod
(JNIEnv * env, jobject obj){
//找到类
jclass cls = (*env)->FindClass(env, "java/util/Date");
//获取构造方法的签名
jmethodID construct_id = (*env)->GetMethodID(env, cls, "<init>", "()V");
//初始化 类
jobject date_obj = (*env)->NewObject(env, cls,construct_id);
//获取方法的签名
jmethodID mid = (*env)->GetMethodID(env, cls, "getTime", "()J");
//访问方法
jlong t = (*env)->CallLongMethod(env, date_obj, mid);
return t;
}
查看类属性和方法的签名
- cd native方法生成的类的文件夹下
- 执行javap -s -p xx.xx.JniUtils