首页 > 代码库 > 使用jni直接访问java对象中的字段

使用jni直接访问java对象中的字段

Java类:UserInfo

public class UserInfo {
	static {
		System.loadLibrary("userinfo");
	}
	// 从JNI中直接访问字段
	public String mUserName;
	public int mUserAge;
	public long mMoney;
	
	public UserInfo() {
		
	}
	
	public int getUserAge() {
		return mUserAge;
	}
	
	public native void setUserName(String name);
	public native void setUserAge(int age);
	public native void setUserMoney(long money);
}

其中三个设置方法,期望使用C实现,这里涉及到JNI中的几个函数:

1、FindClass:找到某个类,并返回jclass对象

2、GetObjectClass: 获取到某个对象的类型,并返回jclass对象

3、GetFieldID:获取到字段的ID

4、SetIntField/SetLongField/SetObjectField:为字段设值

基于上面的几个方法,可以编写代码如下:

/*
 * Class:     com_iflytek_testjni_UserInfo
 * Method:    setUserName
 * Signature: (Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_com_iflytek_testjni_UserInfo_setUserName(JNIEnv *env, jobject obj, jstring jstr) {
	jfieldID fid;

	jclass cls = (*env)->GetObjectClass(env, obj);
	fid = (*env)->GetFieldID(env, cls, "mUserName", "Ljava/lang/String;");
	(*env)->SetObjectField(env, obj, fid, jstr);
}

/*
 * Class:     com_iflytek_testjni_UserInfo
 * Method:    setUserAge
 * Signature: (I)V
 */
JNIEXPORT void JNICALL Java_com_iflytek_testjni_UserInfo_setUserAge(JNIEnv *env, jobject obj, jint age) {
	jclass objClass = (*env)->FindClass(env, "com/iflytek/testjni/UserInfo");
	jfieldID ageID = (*env)->GetFieldID(env, objClass, "mUserAge", "I");
	(*env)->SetIntField(env, obj, ageID, (int)age);
}

/*
 * Class:     com_iflytek_testjni_UserInfo
 * Method:    setUserMoney
 * Signature: (J)V
 */
JNIEXPORT void JNICALL Java_com_iflytek_testjni_UserInfo_setUserMoney(JNIEnv *env, jobject obj, jlong money) {
	jclass objClass = (*env)->FindClass(env, "com/iflytek/testjni/UserInfo");
	jfieldID id = (*env)->GetFieldID(env, objClass, "mMoney", "J");
	(*env)->SetLongField(env, obj, id, (long)money);
}
编写Android.mk后编译,可以测试通过。

注意:由于方法签名、字段名称都是写死在C语言中的,因此代码不能混淆。