JNI獲取並修改Java中類的變數和靜態變數的值
阿新 • • 發佈:2019-02-16
對於JNI的基本使用請移步:Hello JNI
本文主要介紹以下幾個函式的使用:
GetObjectClass
GetFieldID,GetStaticFieldID
Get< Type>Field,GetStatic< Type>Field
Set< Type>Field,SetStatic< Type>Field
案例介紹:通過JNI獲取並修改Java中類的變數值
本文也是基於上面的程式碼繼續新增:
JniDemo中新增name,age變數,和accessField(),accessStaticField()方法。
public class JniDemo {
//路徑:/JNIDemo/app/build/intermediates/classes/debug/com/test/git/jnidemo/JniUtil/JniDemo.class
public String name = "Lucy";
public static int age = 10;
public native String helloJni();
//修改欄位值
public native void accessField();
//修改欄位值(靜態方法)
public native void accessStaticField();
static {
System.loadLibrary("NdkJniDemo");
}
}
生成相應的標頭檔案:
JNIEXPORT void JNICALL Java_com_test_git_jnidemo_JniUtil_JniDemo_accessField
(JNIEnv *, jobject);
JNIEXPORT void JNICALL Java_com_test_git_jnidemo_JniUtil_JniDemo_accessStaticField
(JNIEnv *, jobject);
JniDemo.cpp
通過JNI獲取並修改Java中變數值
對於變數的簽名可以參考:JNI型別
JNIEXPORT void JNICALL Java_com_test_git_jnidemo_JniUtil_JniDemo_accessField
(JNIEnv *env, jobject obj){
//1.獲取jclass obj是JniDemo物件, JNIDemo.class
jclass cls = (*env).GetObjectClass(obj);
//2.獲取jfieldID
//name:屬性名稱,sig:屬性簽名
//jfieldID GetFieldID(jclass clazz, const char* name, const char* sig)
jfieldID fid = (*env).GetFieldID(cls, "name", "Ljava/lang/String;");
//3.修改name的值
//a.獲取name屬性的值 Get<Type>Field
jstring jstr = (jstring) (*env).GetObjectField(obj, fid);
//b.jstring轉成c字串
//isCopy:true複製, false不復制,或者NULL
//const char* GetStringUTFChars(jstring string, jboolean* isCopy)
const char* c_str = (*env).GetStringUTFChars(jstr, JNI_FALSE);
//c.拼接得到新的字串
char new_char[40] = "changed ";
//複製c_str 到 new_char
strcat(new_char, c_str);
//d.c字串轉換成String
jstring new_jstr = (*env).NewStringUTF(new_char);
//e.修改name值
//Set<Type>Field
(*env).SetObjectField(obj, fid, new_jstr);
//釋放資源
(*env).ReleaseStringUTFChars(jstr, c_str);
};
通過JNI獲取並修改Java中靜態變數值
JNIEXPORT void JNICALL Java_com_test_git_jnidemo_JniUtil_JniDemo_accessStaticField
(JNIEnv *env, jobject obj){
//1.獲取jclass
jclass cls = env->GetObjectClass(obj);
//2.獲取age的jfieldID 注意用GetStaticFieldID方法
jfieldID jfid = env->GetStaticFieldID(cls, "age", "I");
//3.通過jfid獲取age的屬性值,注意用GetStaticIntField
jint jage = env->GetStaticIntField(cls, jfid);
jage ++;
//4.修改age的屬性值,注意用GetStaticIntField
env->SetStaticIntField(cls,jfid, jage);
};
MainActivity呼叫
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity-";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
JniDemo jd = new JniDemo();
Log.i(TAG, "helloJni->" + jd.helloJni());
Log.i(TAG, "name修改前: " + jd.name);
jd.accessField();
Log.i(TAG, "name修改後: " + jd.name);
Log.i(TAG, "age修改前: " + jd.age);
jd.accessStaticField();
Log.i(TAG, "age修改後: " + jd.age);
}
}
執行結果:
09-24 12:32:44.021 19457-19457/com.test.git.jnidemo I/MainActivity-: helloJni->hello jni
09-24 12:32:44.021 19457-19457/com.test.git.jnidemo I/MainActivity-: name修改前: Lucy
09-24 12:32:44.021 19457-19457/com.test.git.jnidemo I/MainActivity-: name修改後: changed Lucy
09-24 12:32:44.021 19457-19457/com.test.git.jnidemo I/MainActivity-: age修改前: 11
09-24 12:32:44.021 19457-19457/com.test.git.jnidemo I/MainActivity-: age修改後: 12
擴充套件
JNI獲取並修改Java中Array的值
JniDemo.class
public String[] courses = {"語文", "數學"};
public native void accessArrayField();
com_test_git_jnidemo_JniUtil_JniDemo.h標頭檔案
JNIEXPORT void JNICALL Java_com_test_git_jnidemo_JniUtil_JniDemo_accessArrayField
(JNIEnv *, jobject);
JniDemo.cpp
JNIEXPORT void JNICALL Java_com_test_git_jnidemo_JniUtil_JniDemo_accessArrayField
(JNIEnv *env, jobject jobj){
jclass cls = env->GetObjectClass(jobj);
jfieldID fid = env->GetFieldID(cls, "courses", "[Ljava/lang/String;");
jobjectArray jarray = (jobjectArray) env->GetObjectField(jobj, fid);
env->SetObjectArrayElement(jarray, 0, env->NewStringUTF("英語"));
};
MainActivity.java
Log.i(TAG, "courses修改前: " + jd.courses[0]);
jd.accessArrayField();
Log.i(TAG, "courses修改後: " + jd.courses[0]);
列印結果:
09-24 14:36:23.041 18001-18001/com.test.git.jnidemo I/MainActivity-: courses修改前: 語文
09-24 14:36:23.042 18001-18001/com.test.git.jnidemo I/MainActivity-: courses修改後: 英語