JAVA 支持兩種 field(字段),每個對象的實例都有一個對象字段的複製;全部的對象共享一個類的靜態字段。java
訪問對象字段:
先看一個從本地代碼中訪問對象字段的例子:數組
class InstanceFieldAccess { private String s; private native void accessField(); public static void main(String args[]) { InstanceFieldAccess c = new InstanceFieldAccess(); c.s = "abc"; c.accessField(); System.out.println("In Java:"); System.out.println(" c.s = \"" + c.s + "\""); } static { System.loadLibrary("InstanceFieldAccess"); } }
下面是本地方法的實現:函數
JNIEXPORT void JNICALL Java_InstanceFieldAccess_accessField(JNIEnv *env, jobject obj) { jfieldID fid; /* store the field ID */ jstring jstr; const char *str; /* Get a reference to obj's class */ jclass cls = (*env)->GetObjectClass(env, obj); //第一步 printf("In C:\n"); /* Look for the instance field s in cls */ fid = (*env)->GetFieldID(env, cls, "s", "Ljava/lang/String;"); //第二步 if (fid == NULL) { return; /* failed to find the field */ } /* Read the instance field s */ jstr = (*env)->GetObjectField(env, obj, fid); //第三步 str = (*env)->GetStringUTFChars(env, jstr, NULL); if (str == NULL) { return; /* out of memory */ } printf(" c.s = \"%s\"\n", str); (*env)->ReleaseStringUTFChars(env, jstr, str); /* Create a new string and overwrite the instance field */ jstr = (*env)->NewStringUTF(env, "123"); if (jstr == NULL) { return; /* out of memory */ } (*env)->SetObjectField(env, obj, fid, jstr); }
運行程序,獲得輸出爲:
In C:
c.s = "abc"
In Java:
c.s = "123"
訪問一個對象字段的流程
爲了訪問一個對象的實例字段,本地方法須要作兩步:
首先,經過在類引用上調用 GetFieldID 獲取 field ID(字段ID)、字段名字和字段描述符:
Fid=(*env)->GetFieldID(env,cls,」s」,」Ljava/lang/String;」);
上例中的代碼經過在對象引用obj上調用GetObjectClass獲取到類引用。一旦獲取到字段ID,
你就能夠把對象和字段 ID做爲參數來訪問字段:
Jstr=(*env)->GetObjectField(env,obj,fid);
由於字符串和數組是特殊的對象,因此咱們使用GetObjectField 來訪問字符串類型的實例字段。
除了 Get/SetObjectField,JNI 還支持其它如 GetIntField、SetFloatField 等用來訪問基本類型字段的函數。spa
Ljava/lang/String這個字符串被稱爲JNI field descriptor(字段描述符)。
字符串的內容由字段被聲明的類型決定code
訪問靜態字段:
訪問靜態字段和訪問實例字段類似,看下面這個InstanceFieldAccess 例子的變形:對象
class StaticFielcdAccess { private static int si; private native void accessField(); public static void main(String args[]) { StaticFieldAccess c = new StaticFieldAccess(); StaticFieldAccess.si = 100; c.accessField(); System.out.println("In Java:"); System.out.println(" StaticFieldAccess.si = " + si); } static { System.loadLibrary("StaticFieldAccess"); } }
下面是本地方法StaticFieldAccess.accessField 的實現:ip
JNIEXPORT void JNICALL Java_StaticFieldAccess_accessField(JNIEnv *env, jobject obj) { jfieldID fid; /* store the field ID */ jint si; /* Get a reference to obj's class */ jclass cls = (*env)->GetObjectClass(env, obj); printf("In C:\n"); /* Look for the static field si in cls */ fid = (*env)->GetStaticFieldID(env, cls, "si", "I"); if (fid == NULL) { return; /* field not found */ } /* Access the static field si */ si = (*env)->GetStaticIntField(env, cls, fid); printf(" StaticFieldAccess.si = %d\n", si); (*env)->SetStaticIntField(env, cls, fid, 200); }
運行程序可獲得輸出結果:
In C:
StaticFieldAccess.si = 100
In Java:
StaticFieldAccess.si = 200字符串