1. 程式人生 > >使用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語言中的,因此程式碼不能混淆。